Kotlin代表团如何有用?

我真的很困惑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代表团的好处是什么呢? 这在这里描述。

 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实现委托的方式类似于Groovy等语言中的traits实现。 您可以通过委托编写不同的功能。 科特林的方式也可以被认为更强大,因为你可以“插入”不同的实现。

 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 

你不能用继承来做到这一点。

由于委托模式中的大部分行为可以与委托( b )的目标相同,但是您只是想重写一部分方法以采取不同的行动,所以这很有用。

一个例子是一个InputStream实现,它把所有的工作委托给另一个InputStream但是重写close()方法不关闭底层的流。 这可以实现为:

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

这对创建装饰器和对象组合非常有用。 Effective Java中的Joshua Bloch,第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 } }