🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# 委托 参考规范文档——[委托](http://www.kotlincn.net/docs/reference/delegation.html#%E5%A7%94%E6%89%98) 委托模式也叫代理模式,是最常用的一种设计模式。在委托模式中,如果有两个对象参与处理同一个请求,则接受请求的对象将请求委托给另一个对象来处理,简单来说就是A的工作交给B来做。**委托模式是实现继承的一个很好的替代方式**。在**Kotlin中,委托是通过by关键字实现的,并且主要分为两种形式,一种是类委托,一种是属性委托**。本节我们将对Kotlin中的委托进行详细讲解。 ## 使用委托代替多继承 一种Kotlin中新引入的语法——委托。通过它我们也可以代替多继承来解决类似的问题。 关于委托,可能你会很熟悉。比如你非常了解委托模式,或者你是一名C#开发者,熟悉其中的delegate关键字。简单来说,**委托是一种特殊的类型,用于方法事件委托,比如你调用A类的methodA方法,其实背后是B类的methodA去执行**。 印象中,要实现委托并不是一件非常自然直观的事情。但庆幸的是,**Kotlin简化了这种语法,我们只需通过by关键字就可以实现委托的效果。比如我们之前提过的by lazy语法,其实就是利用委托实现的延迟初始化语法**。我们再来重新回顾一下它的使用: ``` val laziness: String by lazy { // 用by lazy实现延迟初始化效果 println("I will have a value") "I am a lazy-initialized string" } ``` 委托除了延迟属性这种内置行为外,还提供了一种可观察属性的行为,这与我们平常所说的观察者模式很类似。观察者模式在Android开发中应用很广,我们会利用委托在后面介绍它如何改善Android中的观察者模式。 接下来,我们来看看如何通过委托来代替多继承实现需求。请看下面的例子: ``` interface CanFly { fun fly() } interface CanEat { fun eat() } open class Flyer : CanFly { override fun fly() { println("I can fly") } } open class Animal : CanEat { override fun eat() { println("I can eat") } } class Bird(flyer: Flyer, animal: Animal) : CanFly by flyer, CanEat by animal {} fun main(args: Array<String>) { val flyer = Flyer() val animal = Animal() val b = Bird(flyer, animal) b.fly() b.eat() } ``` 有人可能会有疑问:首先,委托方式怎么跟接口实现多继承如此相似,而且好像也并没有简单多少;其次,这种方式好像跟组合也很像,那么它到底有什么优势呢?主要有以下两点: * 1)前面说到接口是无状态的,所以即使它提供了默认方法实现也是很简单的,不能实现复杂的逻辑,也不推荐在接口中实现复杂的方法逻辑。我们可以利用上面委托的这种方式,虽然它也是接口委托,但它是用一个具体的类去实现方法逻辑,可以拥有更强大的能力。 * 2)假设我们需要继承的类是A,委托对象是B、C、我们在具体调用的时候并不是像组合一样A.B.method,而是可以直接调用A.method,这更能表达A拥有该method的能力,更加直观,虽然背后也是通过委托对象来执行具体的方法逻辑的。