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 靜態初始化器的語義相匹配。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章