Kotlin 委托

一、什么是委托?

C#中有委托这么一说,但是在Java中是没有这么一说的。回到Kotlin中又有了委托。那到底什么是委托呢?

委托是软件设计的一种模式,当无法或不想访问某个对象或访问某个对象存在困难时,可以交给委托类来处理。

二、Kotlin中的类委托

类委托:即一个类中定义的方法实际是调用另一个类的对象的方法来实现的。

//1.定义一个接口
interface Base {
    fun print()
}

//2.定义被委托的类
class BaseImpl(val xx: String) : Base {
    override fun print() {
        println("BaseImpl:${xx.toString()}")
    }
}
//3.定义委托类
class BaseDelegate(base:Base):Base by base

fun main(args: Array<String>) {
    val b=BaseImpl("委托类")
    BaseDelegate(b).print()
}
//可以看到委托类并没有实现Base接口,而是通过关键字by,将实现委托给了base

三、属性委托

属性委托指的是一个类的某个属性值不是在类中直接定义,而是将其委托给一个代理类,从而实现对该类属性的统一管理。

属性委托语法格式:val/var<属性名>:<类型> by<表达式>

表达式:就是指委托的代理类

import kotlin.reflect.KProperty

/**
 * 包含属性的被委托类
 */
class Example{
   var p:String by Delegate()
}

/**
 * 定义一个属性委托的类
 * 该类需要包括getValue()方法h和setValue()方法,且参数thisRef为进行委托类的对象,
 * prop为进行委托的属性的对象
 */
class Delegate{
    operator fun getValue(thisRef:Any?,property:KProperty<*>):String{
        return "$thisRef, thank you for delegating '${property.name}' to me!"
    }
    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
        println("$value has been assigned to '${property.name}' in $thisRef.")
    }
}

fun main(args: Array<String>) {
    val e=Example()
    print(e.p)

    e.p="wcystart" //调用setValue()函数
}
//当我们从委托到一个 Delegate 实例的 p 读取时,将调用 Delegate 中的 getValue() 函数, 所以它第一个参数是读出 p 的对象、
//第二个参数保存了对 p 自身的描述 (例如你可以取它的名字)。
//Example@685f4c2e, thank you for delegating 'p' to me!

四、延迟属性Lazy


fun main(args: Array<String>) {
    println(lazyValue) 
    println(lazyValue)
}

/**
 * lazy()是一个函数,接受一个Lambda表达式作为参数,返回一个Lazy<T>
 *  实例的函数,返回的实例可以作为实现延迟属性的委托;
 *  第一次调用get()会执行以传递给Lazy()的lamda表达式并记录结果,后续调用get()只是返回记录的结果
 */
val lazyValue:String by lazy {
   println("computed") //第一次调用输出,第二次调用不执行
    "Hello"
}

computed
Hello
Hello

五、可观察属性

import kotlin.properties.Delegates

/**
 * observable:可用于实现观察者模式
 * Delegates.observable()函数接收两个参数,第二个是属性值变化事件的响应器(handler)。
 * 在属性赋值后会执行事件的响应器(handler),它有三个参数:被赋值的属性、旧值和新值:一个是初始化值,第二个是属性值
 */
class User{
    var name: String by Delegates.observable("初始值") {
        prop, old, new ->
        println("旧值:$old -> 新值:$new")
    }
}

fun main(args: Array<String>) {
    val user=User()
    user.name="第一次赋值"
    user.name="第二次赋值"
}

旧值:初始值 -> 新值:第一次赋值
旧值:第一次赋值 -> 新值:第二次赋值

六、把属性储存在映射中

一个常见的用例是在一个映射(map)里存储属性的值。 这经常出现在像解析 JSON 或者做其他”动态”事情的应用中。 在这种情况下,你可以使用映射实例自身作为委托来实现委托属性。

class Site(val map:Map<String,Any?>){
    val name:String by map
    val url:String by map
}

fun main(args: Array<String>) {
    val site=Site(mapOf("name" to "百度",
            "url" to "www.baidu.com"))

    println(site.name)
    println(site.url)
}

百度
www.baidu.com

如果使用var属性。将map换成MutableMap

class Site(var map: MutableMap<String, Any?>) {
    var name: String by map
    var url: String by map
}

fun main(args: Array<String>) {
    var map: MutableMap<String, Any?> = mutableMapOf(
            "name" to "Google",
            "url" to "www.google.com")

    val site = Site(map)
    println(site.name)
    println(site.url)
}
Google
www.google.com

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值