代理

属性代理

有一个专门的章节来讲述代理属性

用代理实现

代理模式已经被证明是一个继承实现(implementation inheritance)的好方法,Kotlin 无需其他代码,原生支持。Derived 类可以继承 Base 接口,然后把它的 public 方法都代理到一个指定对象上:

  1. interface Base {
  2. fun print()
  3. }
  4. class BaseImpl(val x: Int) : Base {
  5. override fun print() { print(x) }
  6. }
  7. class Derived(b: Base) : Base by b
  8. fun main(args: Array<String>) {
  9. val b = BaseImpl(10)
  10. Deribed(b).print() // prints 10
  11. }

Derived 父类列表中的 by 子句表示 b 会被存储在所有的 Derived 对象的内部,编译器会生成 Base 的所有方法,这些方法会跳向 b

覆写用代理实现的接口成员

覆写的工作方式与我们预期的一致:编译器会使用我们 override 的实现而不是代理对象中的实现。如果我们给 Derived 增加覆写的函数 override fun print() { print("abc") },程序执行后会打印出 “abc” 而不是 “10”。

  1. interface Base {
  2. fun printMessage()
  3. fun printMessageLine()
  4. }
  5. class BaseImpl(val x: Int) : Base {
  6. override fun printMessage() { print(x) }
  7. override fun printMessageLine() { println(x) }
  8. }
  9. class Derived(b: Base) : Base by b {
  10. override fun printMessage() { print("abc") }
  11. }
  12. fun main(args: Array<String>) {
  13. val b = BaseImpl()
  14. Derived(b).printMessage()
  15. Derived(b).printMessageLine()
  16. }

但是,使用这种方式覆写的的成员不会被代理对象的成员调用,因为它们只能访问自己实现的接口成员:

  1. interface Base {
  2. val message: String
  3. fun print()
  4. }
  5. class BaseImpl(val x: Int) : Base {
  6. override val message = "BaseImpl: x = $x"
  7. override fun print() { println(message) }
  8. }
  9. class Derived(b: Base) : Base by b {
  10. // Thie property is not accessed from b's implementation of `print`
  11. override val message = "Message of Derived"
  12. }
  13. fun main(args: Array<String>) {
  14. val b = BaseImpl(10)
  15. val derived = Derived(b)
  16. derived.print()
  17. println(derived.message)
  18. }

https://kotlinlang.org/docs/reference/delegation.html