一,伴生对象
1.类似于java中的静态方法static
class TestCompanion{
//伴生对象使用companion object定义
companion object {
fun doTest(){
}
}
}
//kotlin调用
fun main(args: Array<String>) {
//2种方式
//直接通过类名点Companion去点要调用的方法
TestCompanion.Companion.doTest()
//直接通过类名去点要调用的方法
TestCompanion.doTest()
}
//kotlin和java是100%兼容,在Java中调用
public class TestCompanionJava {
public static void main(String[] args) {
TestCompanion.Companion.doTest();
}
}
在java中调用可见加了一个Companion,但是假设我们在开发是由java转kotlin项目肯定是一点一点的去动代码,那么这里就涉及到静态方法改成kotlin但是调用还是java,怎么办呢?
class TestCompanion{
//伴生对象使用companion object定义
companion object {
//使用该注解,在java中就可以直接类名调用
@JvmStatic
fun doTest(){
}
}
}
//JAVA调用
public class TestCompanionJava {
public static void main(String[] args) {
TestCompanion.doTest();
}
}
2.实现接口
class TestCompanion{
//伴生对象使用companion object定义
//实现一个接口
companion object :InterfaceCompanion {
override fun inter() {
println("伴生对象") }
}
}
/**
* 有两种方法调用方法
*/
fun main(args: Array<String>) {
//1.直接调用方法名
TestCompanion.inter()
//2.实例化伴生对象,再通过对象调用方法名
val companion = TestCompanion.Companion
companion.inter()
//在这里我们测试一下实例
val companion2 = TestCompanion.Companion
println(companion)
println(companion2)
}
输出:
伴生对象
伴生对象
river.service.TestCompanion$Companion@16b98e56
river.service.TestCompanion$Companion@16b98e56
//可见两次实例的物理地址是一样的,说明是同一个实例对象
这种实现接口的伴生对象有什么意义呢?
个人粗浅理解,作为外层类的成员变量,又作为该接口的一个实现类的实例,若只有这一个地方需要使用到这样实现的子类,或者只在此处需要这样定制化的子类,则可以写成这种,类似于匿名内部类的样子,我们不需要知道这个子类是什么,只需要知道他的特性即可;
二.对象表达式
Kotlin 用对象表达式和对象声明来实现创建一个对某个类做了轻微改动的类的对象,且不需要去声明一个新的子类。
/**
* 对象表达式用法
* 通过对象表达式实现一个匿名内部类的对象用于方法的参数中:
*/
class TestCompanion{
//对象表达式实现接口
var param = object : InterfaceCompanion{
override fun inter() {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
//对象表达式继承抽象类
var param2 = object : AbstractObject() {
override fun abMethod(): String {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
}
/**
* 有两种方法调用方法
*/
fun main(args: Array<String>) {
val testCompanion = TestCompanion()
println(testCompanion.param2.name)
}
输出 : name
//上面例子用到的接口和抽象类
//1.接口
interface InterfaceCompanion{
fun inter()
}
//2.抽象类
abstract class AbstractObject{
var name :String = "name"
abstract fun abMethod():String
}
对象表达式的用途,当需要一个对某个类轻微改动后的实例时,又不需要显式的声明此改动后的类,因为用到的地方可能仅此一处,使用对象表达式可以更加简洁;减少了不必要的类,避免类膨胀;