Kotlin-學習筆記-注意事項(二)

1 object(單例)和 companion object(伴生對象)

Kotlin中沒有靜態屬性和靜態方法
用object 修飾的類爲單例(靜態)類,裏面的變量是靜態的(private static,有相應get ,set 方法)
裏面的方法 用 @JvmStatic 修飾的爲靜態的方法(public static),沒有用@JvmStatic 修飾的不是靜態的方法(public),但通過object修飾的靜態類的實例也可以訪問

用companion object 修飾的類爲伴生對象,也是單例(靜態)類(public static),伴生對象在類中只能存在一個 ,所以companion object 後面的類名可以省略。
裏面的變量 會在companion object 所在類裏面生成靜態的成員 (private static,有相應get ,set 方法)同object。
裏面的方法 用 @JvmStatic 修飾的爲靜態的(public static),會在companion object 所在類裏面生成相對應的靜態函數,沒有用@JvmStatic 修飾的不是靜態的(public),但通過object修飾的靜態類的實例也可以訪問

因此 object和companion object 修飾的類爲單例(靜態)類,裏面的成員屬性和成員函數可以當做靜態屬性和靜態函數,已與直接訪問。

2 類繼承(open)

抽象函數或者抽象類 默認就是open類型
除了抽象類和接口默認是可被繼承外,其他類默認是不可以被繼承的(相當於默認都帶有final修飾符)。而類中的方法也是默認不可以被繼承的

如果你想要繼承一個類,你需要使用open關鍵字修飾這個類。
如果你想要繼承一個類的某個方法,這個方法也需要使用open關鍵字修飾。

3 operator操作符

3.1 替代運算操作符。使用方式是 operator 修飾一個方法,方法名爲保留的操作符關鍵字,這樣就可以讓這個操作符的行爲映射到這個方法,也叫操作符重載
注意 操作符僅可以定義爲成員函數或擴展函數,所有的操作符都有一個預定義的英文單詞以便用於重載操作符
如一元 +a 函數名必須是a.unaryPlus()

class Point constructor(var x:Int ,var y:Int){
    operator fun plus(p: Point) {
        x += p.x
        y += p.y
    }
}

fun main(args: Array<String>) {
    val p1 = Point(8,10)
    val p2 = Point(2,3)
    
    val psum = p1 + p2 
    等同於 val psum = p1.plus(p2)
}

3.2 屬性委託(代理)

class Delegate {

     operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
         return "${thisRef}, property '${property.name}' "
     }

     operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
         println("${thisRef} property '${property.name}' is setting value: '$value'")
     }
}

class DelegateProperties{
   var property : String by Delegate()
}

DelegateProperties的property屬性的getter/setter是分別委託給上面這個Delegate類的getValue和setValue方法。

4 operator+componentX( 屬性聲明)

定義如下一個函數

class Object(var name:String,var gender:String){
        operator fun component1() = name
}

函數的名稱一定是 component+數字
這時,如果調用了component1,那麼得到的value就是name

5 by Delegates.observable() 監聽屬性值變化
class User {
    var name: String by Delegates.observable("<no name>") {
        prop, old, new ->
        println("${prop.name}   $old -> $new")
    }
    //等同
    var name: String by Delegates.observable("<no name>", { 
         prop, old, new ->
         
    })

}
6 vetoable(特殊的Delegates.observable)

爲讀/寫屬性返回一個屬性委託,該屬性在更改時 調用指定的回調函數進行判斷,來決定回調是否更改
官網vetoable

var max: Int by Delegates.vetoable(0) { 
    property, oldValue, newValue ->
    newValue > oldValue
}

max 初始值爲1 ,當新值大於舊值時 才允許修改max的值

7 by lazy, lateinit 屬性延遲加載

private lateinit var add: String
val lazyValue: String by lazy { “HelloWorld” }

  1. lzay 後跟表達式,表達式返回值必須和屬性類型一致。第一次調用時開始執行 返回結果 ,後面再調用時,直接返回結果。(lambda表達式裏面最後一行是返回結果,不需要return)
  2. lazy 操作符是線程安全的。
  3. 如果不擔心多線程問題或想提高更多的性能,可以使用 lazy(LazyThreadSafetyMode.NONE){ … }

lateinit 則用於只能生命週期流程中進行獲取或者初始化的變量,比如在 Android 的 onCreate() 中需要初始化的變量,lateinit修飾的變量未初始化前不能調用

8 by Delegates.notNull() 屬性非空強校驗

var name: String by Delegates.notNull()

參考
kotlin 常見 關鍵詞
Kotlin lateinit 和 by lazy

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