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()