1.委托模式
委托模式:操作对象不会去处理某段逻辑,而是会把工作委托给另外一个辅助对象去处理。
例如我们要设计一个自定义类的来实现Set,可以将该实现委托给另一个对象:
class MySet<T> (val helperSet: HashSet<T>) : Set<T> {
override val size: Int
get() = helperSet.size
override fun isEmpty(): Boolean {
return helperSet.isEmpty()
}
override fun iterator(): Iterator<T> {
return helperSet.iterator()
}
override fun containsAll(elements: Collection<T>) = helperSet.containsAll(elements)
override fun contains(element: T) = helperSet.contains(element)
override fun contains(element: T) = false //自己重写该方法来定制功能
fun eat() = println("I can eat.") //新增方法
}
这样就可以让大部分的方法实现调用辅助对象中的方法,少部分的方法实现由自己来重写,甚至加入一些自己独有的方法,那么MySet就会成为一个全新的数据结构类
2.类委托
如上委托模式的代码实现存在一个弊端,如果接口中待实现的方法特别多,那么相应每个都去调用辅助对象中的相应方法实现将会特别复杂
这时候在Kotlin中使用by关键字,再接上受委托的辅助对象,就可以免去之前所写的一大堆模板式的代码了:
class MySet<T>(val helperSet: HashSet<T>) : Set<T> by helperSet {
override fun contains(element: T) = false //自己重写该方法来定制功能
fun eat() = println("I can eat.") //新增方法
}
类委托本质:简化实现委托模式所需要写的很多不必要代码
3.类可以委托给对象的情况
可以的情况:
a.构造函数中传入
class MyList2(theList: ArrayList<String>) : List<String> by theList {
}
b.object的属性
class MyList3 : List<String> by theList {
object theList : ArrayList<String>()
}
c.伴生对象中的属性
class MyList4 : List<String> by theList {
companion object {
val theList: List<String> = ArrayList<String>()
}
}
d.直接创建对象
class MyList6 : List<String> by ArrayList() {
}
e.调用函数获得对象
fun getDdd() : LinkedList<String> {
return LinkedList<String>()
}
class MyList7 : List<String> by getDdd() {
}
不可以的情况:
a.字段
class MyList : List<String> by theList { //编译报错,提示:Unresolved reference: theList
val theList: List<String> = ArrayList<String>()
}
b.构造函数中的变量
class MyList8 : List<String> by theList { //编译报错,提示:Unresolved reference: theList
init {
val theList = ArrayList<String>()
}
}
4.属性委托
属性委托的核心思想是将一个属性(字段)的具体实现委托给另一个对象去完成
可以看到,这里使用by关键字连接了左边的p属性和右边的Delegate类去完成。当调用p属性的时候会自动调用Delegate的getValue()方法,当给p属性赋值的时候会自动调用Delegate类的setValue()方法
class MyClass {
var p by Delegate()
}
Delegate的具体实现:在Delegate类中我们必须实现getValue()和setValue()这两个方法,并且都要使用operator关键字进行声明
class Delegate {
var proValue: Any? = null
//第一个参数用于声明该Delegate类的委托功能可以在什么类中使用
//第二个参数是Kotlin中的一个属性操作类,可用于扩区各种属性相关的值,在当前场景用不着,但必须在方法参数上进行声明
//返回值可以声明成【任何类型】,根据具体的实现逻辑去写就可以了
operator fun getValue(myClass: MyClass, prop: KProperty<*>) : Any? {
return proValue
}
//前两个参数和getValue()相同
//最后一个参数表示具体要赋值给委托属性的值,这个参数类型必须要和getValue()方法返回值的类型保持一致
operator fun setValue(myClass: MyClass, prop: KProperty<*>, value: Any?) {
proValue = value
}
}
现在当我们给p属性赋值时,就会调用Delegate的setValue()方法;当获取p属性的值时,就会调用Delegate类的getValue()方法
如果p属性是使用val关键字声明的,那么就不用在Delegate类中实现setValue()方法,因为它是常量