Kotlin对象表达式

对象表达式(Object expression),对象声明,伴生对象(companion object)详解

对象表达式(Object expression)

Java当中匿名内部类在很多场景下大量使用。Kotlin的对象表达式就是为了解决匿名内部类的一些缺陷而产生的。
  1. 匿名内部类是没有名字的类
  2. 匿名内部类一定是继承了某个父类,或是实现了某个接口
  3. Java运行时将该匿名内部类当做它所实现的接口或是所继承的父类看待。
对象表达式的格式:  Object[: 若干个父类型,中间用逗号分隔]

interface MyInterface{
    fun myPrint(i:Int)
}
abstract class MyAbstractClass{
    abstract val age:Int
    abstract fun printMyAbstractInfo()
}

fun main(args: Array<String>) {
    var myObject=object :MyInterface{
        override fun myPrint(i: Int) {
            println("i的值是$i")
        }
    }
    myObject.myPrint(100)
    println("-------------")
    var myObject2=object {
        init {
            println("初始化完成")
        }
        var myProperty="Hello world"
        fun myMethod()="myMethod()"
    }
    println(myObject2.myProperty)
    println(myObject2.myMethod())
    println("-------------")
    var myObject3=object:MyInterface,MyAbstractClass() {
        override fun myPrint(i: Int) {
            println("i的值$i")
        }
        override val age: Int
            get() = 30
        override fun printMyAbstractInfo() {
            println("printMyAbstractInfo")
        }
    }
    myObject3.myPrint(50)
    println(myObject3.age)
    myObject3.printMyAbstractInfo()
}

注意:

匿名对象只能在局部变量范围内或是被private修饰的成员变量范围内才能被识别出真正的类型。如果将匿名对象当做一个public方法返回的类型或是public属性的类型,那么该方法或是属性的真正类型,就是该匿名对象所声明的父类型,如果没有声明任何父类型,那么其类型就是Any,在这种情况下匿名对象中声明的任何成员都是无法访问的。如下例子:

class MyClass {
    var i:Int=0
    private var myobject=object{  //此处的private是非常重要的,不能去掉否则访问不到output方法
        fun output()= println("output invoked")
         fun addNumber()=i++ //Kotlin对象表达式中的代码可以访问外层的变量,Java外层必须声明为final
    }
    fun myTest(){
        println(myobject.javaClass)
        myobject.output()
    }
}
fun main(args: Array<String>) {
    val myClass=MyClass()
    myClass.myTest()
}

对象声明

并且它总是在Object关键字后跟一个名称,对象声明不是一个表达式,不能用在赋值语句的右边。对象声明的初始化过程是线程安全的。
object DataProviderManager {
    fun registerDataProvider(provider: DataProvider) {
        // ……
    }
    val allDataProviders: Collection<DataProvider>
        get() = // ……
}

伴生对象(companion object)

在kotlin中,与java不同的是,类是没有static方法的。在大多数情况下,Kotlin推荐的做法是使用包级别的函数作为静态方法,在Kotlin会将包级别的函数当做静态方法来提供。 伴生对象默认名字为Companion.

虽然伴生对象的成员看起来像java中的静态成员,但在运行期,他们依旧是真实对象的实例成员,在jvm上,可以将伴生对象的成员真正生成为类的静态方法与属性,这是通过@jvmStatic注解来实现的,伴生对象在编译后会生成一个静态内部类

class MyTest{
    companion object{
        var a:Int=20
        @JvmStatic //@JvmStatic注解可以将伴生对象的成员真正生成为类的静态方法与属性
        fun method(){
            println("method invoked!")
        }
        fun method2(){ 
            println("method2 invoked!")
        }
    }
}
fun main(args: Array<String>) {
    MyTest.method()
    println(MyTest.a)
    MyTest.method2()
}

对象表达式和对象声明之间的区别

  1. 对象表达式是在使用他们的地方立即执行(及初始化)的;
  2. 对象声明是在第一次被访问到时延迟初始化的;
  3. 伴生对象的初始化是在相应的类被加载(解析)时,与 Java 静态初始化器的语义相匹配。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章