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 } }