Kotlin - 关于类的委托的理解
2019-08-08 本文已影响0人
大丸蛇
- 无论是Kotlin官方的文档和别的地方的文档,你都能发现所有讲类的委托都会举这样一个例子
interface Base {
fun print()
}
// 实现此接口的被委托的类
class BaseImpl(val x: String) : Base {
override fun print() {
Log.d("haha", x)
}
}
// 通过关键字 by 建立委托类
class Derived(b: Base) : Base by b
fun main() {
val b = BaseImpl("10")
Derived(b).print() // 输出 10
}
- 上述代码什么意思呢? by子句表示 b 将会在Derived 中内部存储 ,并且编译器将自动生成转发给 b 的所有 print 的方法。通俗的说传入Base的实现类,通过b 创建的实例BaseImpl("10")执行代码,并保存在Derived中。
- 那可能有人就要问了,我对象都创建出来了,直接调用本身的方法不就行了,干嘛非要绕一圈。
- 这就要引出一个设计模式的概念 ,代理模式。 Kotlin中的委托,实际上就是Kotlin 用语法糖来实现代理模式的简洁版。
- 代理模式可以通过代理对象控制另外一个对象,这样的在不修改原先类的情况下,就可以对原先的类增加功能。很好的符合面向对象开闭原则,对修改关闭,对拓展开放。
- 上述例子的代码就显得很鸡肋了,使用了委托,我们肯定会在原先类做一个扩展,于是就有了下列代码。
interface Base {
fun print()
}
// 实现此接口的被委托的类
class BaseImpl(val x: String) : Base {
override fun print() {
Log.d("haha", x)
}
}
// 通过关键字 by 建立委托类
class Derived(b: Base) : Base by b {
fun doMyOwnPrint(){
Log.d("hehe","33")
print()
}
}
fun main() {
val b = BaseImpl("10")
Derived(b).doMyOwnPrint()
// 输出 hehe33
// 输出 haha10
}
- 值得一提的是我们用继承,重写也可以达到同样的目的。不过拓展的风险明显要小于继承,基于拓展优先于继承的理念,Kotlin中类的委托是有一定实用价值的(反正我没用过)。
- 其实除了委托,在kotlin中还有一种语法糖也可以十分简洁的拓展类,那就是扩展(区分“拓展”,但实际上只是一个叫法而已)。
- 下面直接上代码
private fun BaseImpl.printMyText() {
Log.d("33", "")
print()
}
//调用
val a = BaseImpl()
a.printMyText();
- 看起来是不是更加简洁呢。