kotlin - 类委托和属性委托

kotlin - 类委托和属性委托

类委托

类委托是代理模式的应用。类委托的本质就是把这个类需要实现的部分委托给其他对象,相当于是借用其他对象的方法作为自己的实现。
示例代码如下:

interface Outputable {
    fun output(msg: String)
    var type: String
}

class DefaultOutput : Outputable {
    override fun output(msg: String) {
        println("默认输出方式:${msg}")
    }

    override var type: String = "输出设备"
}

//定义Printer类,指定构造参数out作为委托对象
class Printer(out: DefaultOutput) : Outputable by out

//指定新创建的类作为委托对象。
class Projector : Outputable by DefaultOutput() {
    //重写output方法
    override fun output(msg: String) {
        println("投影设备输出:${msg}")
    }
}
//使用
fun main(args: Array<String>) {
    val output = DefaultOutput()
    val printer = Printer(output)
    printer.output("ppt")
    println(printer.type)
    val projector = Projector()
    projector.output("word文档")
    println(projector.type)
}

为类指定委托对象的方式有两种:

  • 通过构造参数指定委托对象。
  • 直接在类定义的by后新建对象。

属性委托

属性委托可以将多个类的类似属性统一交给委托对象集中实现。这样可以避免每个类都单独实现这些属性。
注意:kotlin不会为委托属性生成幕后字段、getter和setter方法,因此委托属性的所有细节都交由委托类去处理。

属性的委托对象,不需要实现任何接口,但是一定要提供operator修饰的setValue()getValue()方法(val属性无需提供getValue()方法)。
示例代码如下:

class PropertyDelegation{
    var name:String by MyDelegation()
}

class MyDelegation{
    private var _backValue:String ="默认值"

    operator fun getValue(propertyDelegation: PropertyDelegation, property: KProperty<*>): String {
        println("${propertyDelegation}${property.name}属性执行get方法")
        return _backValue
    }

    operator fun setValue(
        propertyDelegation: PropertyDelegation,
        property: KProperty<*>,
        newValue: String
    ) {
        println("${propertyDelegation}${property.name}属性执行set方法 ,传入的参数为:${newValue}")
        _backValue=newValue
    }
}
//使用
fun main(args: Array<String>) {
    val pd = PropertyDelegation()
    //调用的是属性委托类的getValue方法
    println(pd.name)
    //调用的是属性委托类的setValue方法
    pd.name="guojingbu"
    println(pd.name)
}

上面输出的结果如下:

com.guojingbu.learning_kotlin.PropertyDelegation@300ffa5d的 name属性执行get方法
默认值
com.guojingbu.learning_kotlin.PropertyDelegation@300ffa5d的 name属性执行set方法 ,传入的参数为:guojingbu
com.guojingbu.learning_kotlin.PropertyDelegation@300ffa5d的 name属性执行get方法
guojingbu

属性监听

kotlin中的属性监听是通过属性委托给Delegates对象的observable()和vetoable()方法,这两个的返回值都是ReadWriteProperty<Any?,T>,这两个方法实现基本相同,唯一的区别是vetoable()的监听方法会返回一个Boolean类型的值,而observable()方法没有返回值。

observable()方法使用示例代码如下:

var observablePro:String by Delegates.observable("默认值"){
    property, oldValue, newValue ->
    println("$property$oldValue 被修改为:$newValue")
}
//使用
fun main(args: Array<String>) {
    println(observablePro)
    observablePro="guojingbu"
    println(observablePro)

}

上面代码输出结果如下:

默认值
var observablePro: kotlin.String 的 默认值 被修改为:guojingbu
guojingbu

vetoable()方法使用示例代码如下:

var vetoablePro:Int by Delegates.vetoable(1){
    property, oldValue, newValue ->
    println("${vetoablePro}${property.name}属性执行set方法 ,传入的参数为:${newValue}")
    newValue>oldValue
}
//使用
fun main(args: Array<String>) {
    println(vetoablePro)
    vetoablePro=2
    println(vetoablePro)
}

上面代码输入结果如下:

1
var vetoablePro: kotlin.Int的 vetoablePro属性执行set方法 ,传入的参数为:2
2

通过上面的代码可以看出如果 newValue>oldValue 返回true,否则返回false,vetoablePro属性的值必须要比原属性大才能设置成功。

属性委托给map处理

kotlin中可以把属性委托给一个Map集合去管理。这样我们就可以通过map集合来访问对象的属性。
示例代码如下:

class Item(val map: Map<String, Any?>) {
    val code: Int by map
    val name: String by map
}
//使用
fun main(args: Array<String>) {
    var item = Item(
        mapOf(
            "code" to 1,
            "name" to "guojingbu"
        )
    )
    println(item.code)
    println(item.name)
    println("-----------------------")
    //其他程序可以通过map来访问数据。
    println(item.map["code"])
    println(item.map["name"])
}

上面这段程序的属性只能读,不能写。如果需要支持读写,可以把Map修改为MutableMap,然后把val关键字修改为var,就可以实现读写属性委托给map集合了。

变量的延迟初始化

通过kotlin的标准委托函数lazy()来对变量延迟初始化。示例代码如下:

fun main(args: Array<String>) {
    val name:String by lazy {
        println("初始化变量name")
        "guojingbu"
    }
    println("第一次访问:$name")
    println("第二次访问:$name")
}

输出结果如下:

初始化变量name
第一次访问:guojingbu
第二次访问:guojingbu

注意:lazy函数只能用于val修饰的只读属性上。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值