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” }
- lzay 後跟表達式,表達式返回值必須和屬性類型一致。第一次調用時開始執行 返回結果 ,後面再調用時,直接返回結果。(lambda表達式裏面最後一行是返回結果,不需要return)
- lazy 操作符是線程安全的。
- 如果不擔心多線程問題或想提高更多的性能,可以使用 lazy(LazyThreadSafetyMode.NONE){ … }
lateinit 則用於只能生命週期流程中進行獲取或者初始化的變量,比如在 Android 的 onCreate() 中需要初始化的變量,lateinit修飾的變量未初始化前不能調用
。
8 by Delegates.notNull() 屬性非空強校驗
var name: String by Delegates.notNull()