Kotlin学习4.7:委托

  • 类委托
  • 属性委托
  • 延时加载



委托模式也叫代理模式,是最常用的一种设计模式。

在委托模式中,如果有两个对象参与与处理同一个请求,则接受请求的对象将请求委托给另一个对象来处理,简单来说A的工作交给B来做。

委托模式是实现继承的一个很好的替代方式。

委托是通过 by 关键字实现的,并且主要分为两种形式,一种是类委托,一种是属性委托。

类委托

大家知道委托是有两个对象完成的,因此可以推测出类委托实际上也包含两个对象,一个是委托类,一个是被委托类。

在委托类中并没有真正的功能方法,该类的功能是通过调用被委托类中的方法实现的。

示例代码如下。

interface Wash{
    fun washDishes()
}
class Child : Wash{
    override fun washDishes() {
        println("child is washing")
    }
}
class Parent : Wash by Child(){}
fun main() {
    var parent = Parent()
    parent.washDishes()
}

kotlin申请SYSTEM_ALERT_WINDOW失败_Kotlin


实际上类委托还有一种写法,就是在委托类继承接口的同时,传入一个被委托类的实例对象。

实例代码如下。

interface Wash{
    fun washDishes()
}
class Child : Wash{
    override fun washDishes() {
        println("child is washing")
    }
}
class Parent(washer: Wash) : Wash by washer
fun main() {
    var child = Child()
    Parent(child).washDishes()
}

kotlin申请SYSTEM_ALERT_WINDOW失败_Kotlin

属性委托

除了类委托之外,Kotlin还支持属性委托,属性委托是指一个类的某个属性值不是在类中直接定义,而是将其委托给一个代理类,从而实现对该类的属性进行统一的管理。

语法格式如下。

val/var <属性名>: <类型> by <表达式>

举一个生活中的委托实例,在过年时,小朋友会把自己的压岁钱交给父母来保管,这就是委托。

示例代码如下。

import kotlin.reflect.KProperty
class Parent(){
    var money: Int = 0
    operator fun getValue(child: Child, property: KProperty<*>): Int{
        println("getValue()方法被调用,修改属性:${property.name}")
        return money
    }
    operator fun setValue(child: Child, property: KProperty<*>, value: Int){
        println("getValue()方法被调用,修改属性:${property.name}、" + "属性值:${value}")
        money = value
    }
}
class Child{
    var money: Int by Parent()
}
fun main() {
    val child = Child()
    println("(1)父母给孩子100元压岁钱")
    child.money = 100
    println("(2)买玩具花了50")
    child.money -= 50
    println("(3)自己还有${child.money}")
}

kotlin申请SYSTEM_ALERT_WINDOW失败_延迟加载_03

延时加载

在Kotlin中,声明变量或者属性的同时要对其进行初始化,否则就会报异常,尽管我们可以定义可空类型的变量,但有时却不想这样做,能不能在使用变量时再进行初始化呢?

为此,Kotlin中提供了延迟加载,又成懒加载,当变量被访问时才会被初始化,这样不仅可以提高程序效率,还可以让程序启动更快。

延迟加载是通过 by lazy 关键字表示的,延迟加载的变量要求声明为val,即不可变变量,相当于Java中用 final 关键字修饰的变量。

延迟加载也是委托的一种形,延迟加载的语法结构如下。

val/var 变量:变量类型 by lazy{
	变量初始化代码
}

需要注意,延迟加载的变量在第一次初始化时会输出代码块中的所有内容,之后再调用该变量时,都只会输出最后一行代码的内容。

延迟加载的具体代码如下。

fun main() {
    val content by lazy {
        println("Hello")
        "World"
    }
    println(content)
    println(content)
}

kotlin申请SYSTEM_ALERT_WINDOW失败_延迟加载_04