Kotlin学习(十八): 委托模式(Delegate)和委托属性(Delegate Properties)

Tooling

委托模式已经被证明是实现继承的一个很好的替代方式,在扩展一个基类并且重写方法时,基类就必须依赖子类的实现,当不断地修改的时候,基类就会失去当初的性质,Kotlin中就将类默认为final,确保不会被修改。

有一种模式是装饰器模式,本质就是创建一个新类,实现与基类一样的接口,并且将类的实现作为一个字段保存,这样就能在基类不被修改就能直接修改基类的实例。但是这样的缺点是会造成很多的样板代码。

class DelegatingCollection<T> : Collection<T> {
   
    private val innerList = mutableListOf<T>()
    override val size: Int
        get() = innerList.size

    override fun contains(element: T): Boolean = innerList.contains(element)

    override fun containsAll(elements: Collection<T>): Boolean = innerList.addAll(elements)

    override fun isEmpty(): Boolean = innerList.isEmpty()

    override fun iterator(): Iterator<T> = innerList.iterator()

}

当你实现Collection接口的时候,需要重写这几个方法,这里面的代码量是很多的,但是如果用了委托,那么代码就是这样的

class DelegatingCollection2<T>(innerList: Collection<T> = mutableListOf<T>()) : Collection<T> by innerList

这么简单?就能实现那几个方法?我们来看一下生成的代码

是不是省去了很多手写的代码量,下面我们来介绍这种属性。

委托模式(Delegate)

Kotlin支持委托模式,是允许对象组合实现与继承相同的代码复用的,简单来说就是操作的对象不用自己去执行,而是将任务交给另一个对象操作,这样的模式就叫委托模式,被操作的对象叫委托

委托模式是有两个对象参与处理同一个请求,接受请求的对象将请求委托给另一个对象来处理。

类委托

同样我们用上面集合的栗子,现在我们已经是委托到一个对象了,如果我们要修改集合里面的方法的时候,可以直接重写,而不用重复的去写新的方法,下面我们来在一个集合里面插入数据,并且获取插入的次数。

下面代码是默认实现MutableCollection接口,获取插入的次数

class DefaultCollection<T> : MutableCollection<T> {
   
    private val innerList = mutableListOf<T>()
    private var addedSum = 0

    override fun add(element: T): Boolean {
   
        addedSum++
        return innerList.add(element)
    }

    override fun addAll(elements: Collection<T>): Boolean {
   
        addedSum += elements.size
        return innerList.addAll(elements)
    }
    override val size: Int
        get() = innerList.size

    override fun contains(element: T): Boolean = innerList.contains(element)

    override fun containsAll(elements: Collection<T>): Boolean = innerList.addAll(elements)

    override fun isEmpty(): Boolean = innerList.isEmpty()

    override fun iterator(): MutableIterator<T> = innerList.iterator()

    override fun clear() = innerList.clear()

    override fun remove(element: T): Boolean = innerList.remove(element)

    override fun removeAll(elements: Collection<T>): Boolean = innerList.removeAll(elements)

    override fun retainAll(elements: Collection<T>): Boolean {
   
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }

}

实现类委托

class DelegatingCollection3<T>(private val innerList: MutableCollection<T> = HashSet<T>()) : MutableCollection<T> by innerList {
   
    private var addedSum = 0

    override fun add(element: T): Boolean {
   
        addedSum++
        return innerList.add(element)
    }

    override fun addAll(elements: Collection<T>): Boolean {
   
        addedSum += elements.size
        return innerList.addAll(elements)
    }
}

是不是省去很多无用的代码,只需要重写我们需要的方法addaddAll,其他没有写出来的方法全部都交给委托来实现。

而且没有对底层集合的实现方法引入任何的依赖,所以对被调用的操作具有完全的控制,如不用担心集合是不是通过循环中调用add来实现addAll

委托属性(Delegate Properties)

有一种属性,在使用的时候每次都要手动实现它,但是可以做到只实现一次,并且放到库中,一直使用,这种属性称为委托属性。
委托属性包括:

  • 延迟属性(lazy properties):数据只在第一次被访问的时候计算。
  • 可观察属性(observable properties):监听得到属性变化通知。
  • Map委托属性(Storing Properties in a Map):将所有属性存在Map中。
class Foo {
   
    var p: String by Delegate()
}

委托模式的语法是val/var <property name>: <Type> by <expression>by后面的expression就是委托的部分,会将属性的get()set()委托给getValue()setValue()方法。

class Foo {
   
    private val delegate = Delegate()

    var p: String
        set(value: String) = delegate.setValue(...
  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值