Kotlin入門-帶着問題,理解 對象表達式和對象聲明

在這裏插入圖片描述

前言

本文我們需要了解幾個點。
①object與any的區別?
②private跟非private返回值的區別?
③Kotlin中單例模式怎麼實現?又如何調用?
④伴生對象什麼時候產生?可以如何調用?
⑤對象表達式、聲明對象、伴生對象 初始化的時機?

本節目錄不重要。帶着這些問題就可以了。


作用

Kotlin的對象表達式,再一次簡化了,對某個類做輕微改動時,且不需要去聲明一個新的子類。


對象表達式

通過匿名內部類

與java一樣,或繼承、或實現、或通過構造函數傳值給其參數。

匿名對象只在本地和私有作用域中聲明

範例一
window.addMouseListener(object : MouseAdapter() {
    override fun mouseClicked(e: MouseEvent) { /*……*/ }

    override fun mouseEntered(e: MouseEvent) { /*……*/ }
})

知識點複習

理解一下Kotlin中,object與any的區別

  • any
    定義的方法有:toString()、equals()、hashCode() 3個
  • Object類
    定義的方法有:toString()、equals()、hashCode()、getClass()、clone()、finalize()、notify()、notifyAll()、wait()、wait(long)、wait(long,int) 11個

我們看一段英文解析,或許更加清晰。

Kotlin compiler treats kotlin.Any and java.lang.Object as two different types,
but at runtime they are represented with the same java.lang.Object class.

編譯器認爲Any和Object是不同的類型;但是在運行時,Any和Object表現出來是一樣的。

這也是Kotlin可以和Java互通的一個提現。運行時,我們都一樣的。

解析

  • object:MouseAdapter即是new MouseAdapter()
  • 如果不需要 super繼承,僅需要一個object怎麼寫呢
	    private fun foo() = object {
            val x: String = "x"
        }

把冒號 後面的去掉

範例二
class C {
    // 私有函數,所以其返回類型是匿名對象類型
    private fun foo() = object {
        val x: String = "x"
    }

    // 公有函數,所以其返回類型是 Any
    fun publicFoo() = object {
        val x: String = "x"
    }

    fun bar() {
        val x1 = foo().x        // 沒問題
        val x2 = publicFoo().x  // 錯誤:未能解析的引用“x”
    }
}

注意
留意上述範例中的 註釋部分

  • private函數,會返回 匿名對象類型
  • 非private函數,返回的是Any類型

對象聲明

Kotlin 使用 object 關鍵字來聲明一個對象

通過對象聲明,可以獲得一個單例單例單例單例 重要的事情說三遍

範例
object DataProviderManager {
    fun registerDataProvider(provider: DataProvider) {
        // ……
    }

    val allDataProviders: Collection<DataProvider>
        get() = // ……
}

這就是對象聲明。
彷彿是你聲明瞭一個變量一樣

如何調用呢?

DataProviderManager.registerDataProvider(……)

單例的調用不用getInstance了。砍砍砍,砍代碼量啊

來看範例一
var data1 = DataProviderManager
var data2 = DataProviderManager
data1.name = "test"
print("data1 name = ${data2.name}")

//這裏data1.name 和data2.name是一樣的

注意
object聲明的單例,只能通過類名來訪問!!!
Kotlin的單例,避免了getInstance,直接調用。
砍砍砍,砍代碼量啊

看個範例二
class Engineer {
    var name = "wangxueming"
    object Info {
        var sex = "man"
        fun showName(){
            print{"desk legs $name"} // 錯誤,不能訪問到外部類的方法和變量
        }
    }
}
fun main(args: Array<String>) {
    var wxm = Engineer()
    wxm.Info.sex // 錯誤,不能通過外部類的實例訪問到該對象
    Engineer.Info.sex // 正確
}

通過object聲明的對象,是單例,而且!只能!通過 類名 範文。不得不說,這避免了不少麻煩事。
明擺的事情!我訪問單例,肯定就是那麼個實例。


伴生對象

用 companion 關鍵字標記
與外部類關聯在一起!!!如影隨形
可以直接通過外部類訪問到對象的內部元素

範例
class MyClass {
    companion object Factory {
        fun create(): MyClass = MyClass()
    }
}
val instance = MyClass.create()   // 訪問到對象的內部元素

也可以這樣

class MyClass {
    companion object {
    }
}

val x = MyClass.Companion

注意

  • 伴生對象並不是靜態成員, 是 實例成員
  • 一個class裏面只能聲明一個內部關聯對象
  • 即關鍵字 companion 只能使用一次

對象表達式和對象聲明之間的語義差異

  • 對象表達式是在使用他們的地方
    是立即執行的
  • 對象聲明是在第一次被訪問到時
    是延遲初始化的
  • 伴生對象的初始化
    是在相應的類被加載(解析)時,與 Java 靜態初始化器的語義相匹配

小結

總體來說,在Kotlin中,通過object實現了單例,並簡化了單例模式下實例的調用方式;
通過伴生對象,解決了部分的 初始化需求,但是,又在一些情況下,弱化伴生對象的存在(companion object修飾的類名可以不寫)。

將減少代碼量,作爲最高意志。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章