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

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