kotlin之委托介绍

2021-01-14 15:05:28 浏览数 (1)

image.png

委托

委托模式是软件设计模式中的一项基本技巧。

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

委托模式是一项基本技巧,许多其他的模式,如状态模式、策略模式、访问者模式本质上是在更特殊的场合采用了委托模式

使用java举例:

代码语言:javascript复制
 class RealPrinter { // the "delegate"
     void print() { 
       System.out.print("something"); 
     }
 }
 
 class Printer { // the "delegator"
     RealPrinter p = new RealPrinter(); // create the delegate 
     void print() { 
       p.print(); // delegation
     } 
 }
 
 public class Main {
     // to the outside world it looks like Printer actually prints.
     public static void main(String[] args) {
         Printer printer = new Printer();
         printer.print();
     }
 }

可以看到代码中printer 最终其实调用了RealPrinter的方法。

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

Kotlin中实现委托比较方便,Kotlin 通过关键字 by 实现委托。

类委托

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

实际例子: 默认实现的代码:

代码语言:javascript复制
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.
    }

}

通过委托实现的代码:

代码语言:javascript复制
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)
    }
}

属性委托

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

属性委托语法格式:

代码语言:javascript复制
val/var <属性名>: <类型> by <表达式>
  • var/val:属性类型(可变/只读)
  • 属性名:属性名称
  • 类型:属性的数据类型
  • 表达式:委托代理类

by 关键字之后的表达式就是委托, 属性的 get() 方法(以及set() 方法)将被委托给这个对象的 getValue() 和 setValue() 方法。属性委托不必实现任何接口, 但必须提供 getValue() 函数(对于 var属性,还需要 setValue() 函数)。

代码语言:javascript复制
import kotlin.reflect.KProperty
// 定义包含属性委托的类
class Example {
    var p: String by Delegate()
}

// 委托的类
class Delegate {
    operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
        return "$thisRef, 这里委托了 ${property.name} 属性"
    }

    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
        println("$thisRef 的 ${property.name} 属性赋值为 $value")
    }
}
fun main(args: Array<String>) {
    val e = Example()
    println(e.p)     // 访问该属性,调用 getValue() 函数

    e.p = "Runoob"   // 调用 setValue() 函数
    println(e.p)
}

0 人点赞