Kotlin学习:第八章(2)类委托和委托属性

本文介绍了Kotlin中如何通过类委托和委托属性实现接口方法的委派,展示了如何利用by关键字简化大量模板代码,并说明了如何重写特定方法和扩展数据结构的功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

8.2类委托和委托属性

委托是一种设计模式,它的基本概念是:操作对象自己不会去处理某段逻辑,而是会把工作委托给另外一个辅助对象去处理。在Java中并没有委托,而像C#等语言就对委托进行了原生得支持。

8.2.1类委托

核心思想:将一个类的具体实现委托给另一个类去完成。

举一个例子:定义一个MySet,并让它实现Set接口:

class MySet<T>(val helperSet: HashSet<T>) : Set<T> {
    override val size: Int
    get() = helperSet.size

    override fun contains(element: T) = helperSet.contains(element)

    override fun containsAll(elements: Collection<T>) = helperSet.containsAll(elements)

    override fun isEmpty() = helperSet.isEmpty()

    override fun iterator() = helperSet.iterator() 
}

可以看到,MySet的构造函数接收了一个HashSet参数,这就相当于一个辅助对象。然后在Set接口所有的方法实现中,我们都没有进行自己的实现,而是调用了辅助对象相应的方法实现,这就是一种委托模式。

这种写法有啥好处呢? 既然是调用辅助对象的方法实现,那不如直接使用辅助对象得了。但是我们想让部分方法实现由自己来重写,甚至加一些自己独有的方法,那么MySet就会成为一个全新的数据结构,这就是委托模式的意义所在。

但是存在一个问题​,如果接口待实现的方法比较少那还行,如果有几十个甚至上百个方法话,那可不太妙。针对这个问题有什么解决方案呢?在Kotlin中可以通过类委托来解决。

Kotlin中委托使用的关键字是by,我们只需要在接口声明的后面使用by关键字,再接上受委托的辅助对象就可以免去之前所写的一大堆模板代码了。如下所示:

class MySet<T>(val helperSet: HashSet<T>) : Set<T> by helperSet {  
}

借助类委托的功能之后,代码明显简化了很多,如果我们想对某个方法进行重写,只需要单独重现那一个方法就可以了,其它方法仍然可以享受类委托所带来的便利,如下所示:

class MySet<T>(val helperSet: HashSet<T>) : Set<T> by helperSet {  
    fun helloWorld() = println("Hello World!")
    override fun isEmpty() = false
}

我们新增了一个新方法,并且重写了isEmpty()函数,虽然这是一种错误写法,但只是为了演示下而已。至于其他Set接口中的功能,则和HashSet保持一致。这就是Kotlin类委托所能实现的功能。

8.2.2委托属性

核心思想:将一个属性(字段)具体实现委托给另一个类去完成。

语法结构:

class MyClass{
var p by Delegate()
}

可以看到,这种写法代表将p属性的具体实现委托给了Delegate类去完成。

image.png

当调用p属性时会自动调用Delegate类的getValue()方法,当给p属性赋值的时候会自动调用Delegate类的setValue()方法,所以我们必须实现这俩个函数,而且这俩个函数都需要使用operator关键字进行声明。

接着我们对Dletegate类进行具体实现:

class Delegate{
    var propValue: Any? = null
    operator fun getValue(myClass: MyClass,prop: KProperty<*>):Any?{
        return propValue
    }
    operator fun setValue(myClass: MyClass,prop: KProperty<*>,value: Any?){
        propValue = value
    }
}

getValue,setValue第一个参数用于声明Delegate类得委托功能可以再什么类中使用。第二的参数KProperty<*>时Kotlin中一个属性操作类,可以用于获取各种属性相关的值。在当前场景下虽然用不着,但必须在方法参数上进行声明。另外<*>这种泛型的写法表示你不知道或者不关心泛型的具体类型,只是为了通过语法编译而已。而setValue第三个参数value表示具体要赋给委托属性的值,这个参数得类型和getValue方法的范围值类型保持一致。

要注意如果在MyClass中的p是val的话,该属性是无法在初始化后被重新赋值的,因此也没有必要实现setValue方法,只需要实现getValue方法即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值