首页 文章

kotlin委托如何有用?

提问于
浏览
7

我对kotlin代表团感到很困惑 . 让我来描述这里的常规多态方法,它看起来与kotlin delgation相同 .

interface Base {
    fun print()
}
class BaseImpl(val x: Int) : Base {
    override fun print() { print(x) }
}
fun main(args: Array<String>) {
    val b : Base = BaseImpl(10)
    b.print() // prints 10
}

我可以将任何实现的 Base 接口类传递给 b 变量来调用指定类的对象的方法 . 那么 kotlin 代表团的好处是什么?这描述了here .

interface Base {
    fun print()
}
class BaseImpl(val x: Int) : Base {
    override fun print() { print(x) }
}
class Derived(b: Base) : Base by b // why extra line of code? 
                                   // if the above example works fine without it.
fun main(args: Array<String>) {
    val b = BaseImpl(10)
    Derived(b).print() // prints 10
}

我知道这是两个代码都正常工作的简单方案 . 应该有代表团的好处,这就是kotlin引入它的原因 . 有什么不同?以及kotlin委托如何有用?请给我一个工作实例来比较多态方法 .

3 回答

  • 5

    还记得你实现委托的方式类似于Groovy等语言中的_2490452实现 . 您可以通过代表组合不同的功能 . Kotlin的方式也可以被认为更强大,因为你也可以实现不同的实现 .

    interface Marks {
      fun printMarks()
    }
    
    class StdMarks() : Marks {
      override fun printMarks() { println("printed marks") }
    }
    
    class CsvMarks() : Marks {
      override fun printMarks() { println("printed csv marks") }
    }
    
    interface Totals {
      fun printTotals()
    }
    
    class StdTotals : Totals {
      override fun printTotals() { println("calculated and printed totals") }
    }
    
    class CheatTotals : Totals {
      override fun printTotals() { println("calculated and printed higher totals") }
    }
    
    class Student(val studentId: Int, marks: Marks, totals: Totals) 
      : Marks by marks, Totals by totals
    
    fun main(args:Array<String>) {
      val student = Student(1,StdMarks(), StdTotals())
      student.printMarks()
      student.printTotals()
      val cheater = Student(1,CsvMarks(), CheatTotals())
      cheater.printMarks()
      cheater.printTotals()
    }
    

    输出:

    printed marks
    calculated and printed totals
    printed csv marks
    calculated and printed higher totals
    

    你不能通过继承来做到这一点 .

  • 4

    它很有用,因为Delegation Pattern大多数行为都可以与委托的目标相同( b ),但您只想覆盖方法的子集以采取不同的行为 .

    一个示例是 InputStream 实现,它将所有工作委托给另一个 InputStream 但覆盖 close() 方法以不关闭基础流 . 这可以实现为:

    class CloseGuardInputStream(private val base: InputStream)
        : InputStream by base {
        override fun close() {}
    }
    
  • 3

    它对于创建装饰器和对象组合非常有用 . 约书亚布洛赫在Effective Java,第2版,第16项'赞成组合而不是继承'中展示了一个很好的例子:继承是易于破解的,而装饰则不是 .

    遗产:

    class LoggingList<E> : ArrayList<E>() {
    
        override fun add(e: E): Boolean {
            println("added $e")
            return super.add(e)
        }
    
        override fun addAll(e: Collection<E>): Boolean {
            println("added all: $e")
            return super.addAll(e) // oops! Calls [add] internally.
        }
    
    }
    

    代表团:

    class LoggingList<E>(delegate: MutableList<E>) : MutableList<E> by delegate {
    
        override fun add(e: E): Boolean {
            println("added $e")
            return delegate.add(e)
        }
    
        override fun addAll(e: Collection<E>): Boolean {
            println("added all: $e")
            return delegate.addAll(e) // all OK
            // it calls [delegate]'s [add] internally, not ours
        }
    
    }
    

相关问题