在Kotlin中,行为委托是通过关键字by在类的签名中实现的。这允许将接口(或多个接口)的方法调用自动传递给其他实现对象,从而减少样板代码并简化组合。
接口委托的出现是为了解决多重继承的限制和缺陷。这是"优先组合而不是继承"的理念——委托行为而不依赖于类的层次结构。这一思想借鉴自组合更为流行的语言(例如Go,Scala)。
在Java及其他语言中,通常需要手动创建接口并实现每个方法,将逻辑传递给另一个字段(对象适配器模式),而当方法数量增加时,这很快就会过时。
Kotlin允许通过by以声明方式委托接口:
interface Logger { fun log(msg: String) } class ConsoleLogger: Logger { override fun log(msg: String) = println(msg) } class Service(logger: Logger): Logger by logger { fun doWork() { log("工作开始") // ... } } val service = Service(ConsoleLogger()) service.doWork()
关键特性:
如果在Service类中添加具有相同签名的自定义接口方法,会发生什么?
自定义实现"覆盖"了委托的实现——也就是说,类中显式定义的方法优先:
class Service(logger: Logger): Logger by logger { override fun log(msg: String) = println("前缀: $msg") }
一个类能否将多个接口委托给不同对象?
可以,类可以实现并将多个接口委托给不同的对象,但每个接口只能委托给一个对象:
class Service( logger: Logger, tracker: Tracker ): Logger by logger, Tracker by tracker
接口委托与通过by的属性委托有什么区别?
类手动实现接口,每个方法调用代理,当添加新方法时忘记更新代理,从而导致错误。
优点:
缺点:
使用语言层面的委托,仅非标准方法在类内部实现,新功能可以在无需大幅更改的情况下添加。
优点:
缺点: