Kotlin学习之委托机制

Posted 扈扈哈嘿

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Kotlin学习之委托机制相关的知识,希望对你有一定的参考价值。

类的委托

       委托模式可以很好的替代实现继承,kotlin本身支持需要零样板代码,一个类Derived 可以继承Base并委托它所有的public 方法到一个指定的类:

interface Base
fun print()

class BaseImpl(val x: Int) : Base
override fun print() print(x)

class Derived(b: Base) : Base by b
fun main()
val b = BaseImpl(10)
Derived(b).print() // prints 10


这个在父类后面的by指定b存储为Derived的内部对象,编译器会生成Base的所有方法寄于到b上。

属性的委托

       属性的委托指的一个类的某个属性的值不是在类中直接进行定义,而是由某个类的方法来进行 setter 和 getter。默认属性委托都是线程安全的。属性委托适合那些属性的需要复杂的计算但是计算过程可以被重用的场合。

定义一个被委托的类

       该类需要包含 getValue() 方法和 setValue() 方法,且参数 thisRef 为进行委托的类的对象,prop 为进行委托的属性的对象。

“`
class Delegate

private var message = "Default Message"

operator fun getValue(thisRef: Any?, prop: KProperty<*>): String 
    return "$prop.name = $message from $thisRef"


operator fun setValue(thisRef: Any?, prop: KProperty<*>, value: String) 
    message = value

“`

定义包含属性委托的类

class Example
var msg: String by Delegate()

访问该属性

val e = Example()
println(e.msg)  //  msg = Default Message
e.msg = "New Message"
println(e.msg)  //  msg = New Message

       在使用属性委托时,被委托的类的方法(即接收者)的返回值必须与委托的属性相同或者其父类。

标准委托

       Kotlin 的标准库中已经内置了很多工厂方法来实现属性的委托。

lazy

       lazy 用于进行惰性加载,即第一次使用时才执行初始化的操作。

Observable

       observable 可以用于实现观察者模式。

定义包含被委托的属性的类

       Delegates.observable 接收三个参数:包含委托的属性的元数据的 KProperty 对象,旧值,新值。

class User 
var name: String by Delegates.observable("&lt;init value>") 
    prop, old, new ->
    if (old != new) 
        println("\\\\$old -> $new")
    

访问该属性
val user = User()
user.name = "first" //  <init value> -> first
user.name = "first"
user.name = "second"    //  first -> second

       也可以使用 vetoable 代替 observable,该方法拥有布尔类型的返回值,返回 false 的话可以取消对该属性的修改。
在以上 User 中定义一个新属性。

var age: Int by Delegates.vetoable(0) 
prop, old, new ->
println("$old -> $new")
if (new < 20) true else false

访问属性:

user.age = 10   //  0 -> 10
println(user.age)   //  10
user.age = 20   //  10 -> 20
println(user.age)   //  20

NotNull

       notNull 适用于那些无法在初始化阶段就确定属性值的场合。

class Foo 
var notNullBar: String by Delegates.notNull<String>()
foo.notNullBar = "bar"
println(foo.notNullBar)

       需要注意,如果属性在赋值前就被访问的话则会抛出异常。

以 Map 形式保存属性的值

       Kotlin 中有一种特别的委托,可以以 Map 作为一个类的构造方法的参数,访问该类的属性就是访问该 Map 的键值对。这种做法非常类似 Groovy 中的带名构造方法。
要实现这一功能需要得意于 Kotlin 内置的属性的扩展方法 kotlin.properties.getValue
例:

import kotlin.properties.getValue

class Person(val map: Map<String, Any?>) 
val name: String by map
val age: Int by map

可以像普通类一样访问其各个属性:

val person = Person(mapOf(
    "name" to "John",
    "age" to 25
))
println(person.name)
println(person.age)

       对于可变值,可以使用 MutableMap 代替,并导入扩展方法 kotlin.properties.setValue。

import kotlin.properties.setValue

class MutablePerson(val map: MutableMap<String, Any?>) 
var name: String by map
var age: Int     by map

以上是关于Kotlin学习之委托机制的主要内容,如果未能解决你的问题,请参考以下文章

Android学习之基础知识八—Android广播机制

IOS学习之NSNotificationCenter消息机制

Kotlin学习之反射

Kotlin学习之双冒号

Kotlin学习之双冒号

Kotlin学习之变量和函数的讲解