1. 类的委托
委托模式 给实现继承提供了很好的代替方式, Kotlin 在语法上支持这一点,所以并
不需要什么样板代码。 Derived 类可以继承 Base 接口并且指定一个对象代理
它全部的公共方法:
// 类的委托
// AOP(面向方面编程)
interface Base
{
fun print()
}
class BaseImpl(val x:Int):Base
{
override fun print() {
println(x)
}
}
class Child1(b:Base):Base by b
{
fun getName():String
{
return "Bill"
}
}
class Child2(b:Base):Base by b
{
}
class Child3(b:Base):Base by b
{
}
fun main(args: Array<String>)
{
val b = BaseImpl(10)
Child1(b).print()
Child2(b).print()
Child3(b).print()
}
在 Child1的父类列表中的 by 从句会将 b 存储在 Child1内部对象,并
且编译器会生成 Base 的所有方法并转给 b 。
2. 委托属性
很多常用属性,虽然我们可以在需要的时候手动实现它们,但更好的办法是一次实
现多次使用,并放到库。比如:
- 延迟属性:只在第一次访问是计算它的值
- 观察属性:监听者从这获取这个属性
更新的通知 在 map 中存储的属性,而不是单独存在分开的字段为了满足这些情形,Kotllin 支持代理属性:
class Example {
var p: String by Delegate()
}
语法结构是: val/var : by 在 by 后
面的属性就是代理,这样这个属性的 get() 和 set() 方法就代理给了它。
属性代理不需要任何接口的实现,但必须要提供 get() 方法(如果是变量还需要
set() 方法)。像这样:
class MyClass1
{
// 将name属性委托给Delegate类
var name:String by Delegate()
}
class MyClass2
{
var name:String by Delegate()
}
// 属性委托类
class Delegate
{
var name:String = ""
operator fun getValue(thisRef:Any?, property:KProperty<*>):String
{
// 获取thisRef指定的类名
val className = thisRef.toString().substringBefore('@')
println("getValue被调用")
println("${className}.get已经被调用")
return name
}
operator fun setValue(thisRef:Any?, property:KProperty<*>,value:String)
{
// 获取thisRef指定的类名
val className = thisRef.toString().substringBefore('@')
println("setValue被调用")
println("${className}.set已经被调用")
name = value
}
}
fun main(args: Array<String>)
{
var c1 = MyClass1()
var c2 = MyClass2()
c1.name = "Bill"
c2.name = "Mike"
println(c1.name)
println(c2.name)
}
输出:
委托属性的要求:
只读属性 (val),委托必须提供一个名字叫 get 的方法并接受如下参数:
- 接收者–必须是相同的,或者是属性拥有者的子类型
- 元数据–必须是 PropertyMetadata 或这它的子类型
这个函数必须返回同样的类型作为属性。
可变属性 (var),委托必须添加一个叫 set 的函数并接受如下参数:
- 接受者–与 get() 一样 元数据–与 get() 一样
- 新值–必须和属性类型一致 或是它的字类型
3.委托类的初始化函数
如果委托类有主构造器,也可以向主构造器传入一个初始化函数。这是可以定义一个委托函数的返回值是委托类,并在委托时指定初始化函数。
import kotlin.reflect.KProperty
// 委托类的初始化函数
public fun <T> delegate(initializer:()->T):Delegate1<T> = Delegate1(initializer)
class MyClass11
{
// 将name属性委托给delegate
var name:String by delegate {
println("MyClass1.name初始化函数调用")
"<MyClass1>"
}
}
class MyClass22
{
var name:String by delegate {
println("MyClass2.name初始化函数调用")
"<MyClass2>"
}
}
// 属性委托类
class Delegate1<T>(initializer:()->T)
{
var name:String = ""
var className = initializer()
operator fun getValue(thisRef:Any?, property: KProperty<*>):String
{
println("getValue被调用")
println("${className}.get已经被调用")
return name
}
operator fun setValue(thisRef:Any?, property: KProperty<*>, value:String)
{
println("setValue被调用");
println("${className}.set已经被调用")
name = value
}
}
fun main(args: Array<String>)
{
var c1 = MyClass11()
var c2 = MyClass22()
c1.name = "Bill"
c2.name = "Mike"
println(c1.name)
println(c2.name)
}
输出: