问题的历史:
“委托”模式在许多面向对象语言中都是众所周知的原则,它是将工作从一个对象转移给另一个对象。在Java中,委托是通过内部字段和方法代理手动实现的。在Kotlin中,委托被引入到了语法层面,使用关键字by。
问题:
在Java中实现委托模式会导致“神圣的”代理类,充满模板代码,并且在维护接口方面消耗大量人力。难以维护接口合同的更新和更改委托对象。
解决方案:
Kotlin允许创建类,通过class Foo(...) : MyInterface by delegateObj将接口的方法委托给另一个对象,而不是直接实现该接口。这样可以编写简洁明了的代码,消除繁琐,同时保持灵活性。
代码示例:
interface Base { fun print() } class BaseImpl(val x: Int) : Base { override fun print() = println(x) } class Derived(b: Base) : Base by b fun main() { Derived(BaseImpl(42)).print() // 42 }
关键特性:
声明类是否可以改变特定方法的行为,尽管有委托?
可以 — 如果在委托类(Derived)中显式实现接口方法,它将“重写”特定方法的委托行为。
示例:
class Derived(b: Base) : Base by b { override fun print() = println("Overrided!") }
是否可以将多个接口委托给不同的对象?
不可以,在Kotlin中,不能在一个声明中将多个不同的接口委托给不同的对象。必须编写手动委托类,或者如果架构允许,可以结合继承和委托。
委托是否仅适用于接口,还是也适用于抽象类?
只能委托接口,而不是抽象类 — 因为抽象类可能有状态和受保护的方法,这与通过by声明的委托不兼容。
开发人员手动实现委托模式,用于大型接口的十几个方法。在每次扩展接口时,忘记添加新的代理方法。代码膨胀,错误增多。
优点:
缺点:
使用by语法实现接口的自动委托。可以轻松更改实现并在运行时替换委托,而无需在维护合同时冒风险。
优点:
缺点: