我对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
}
Run Code Online (Sandbox Code Playgroud)
我可以将任何实现的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
}
Run Code Online (Sandbox Code Playgroud)
我知道这是两个代码都正常工作的简单方案.应该有代表团的好处,这就是kotlin引入它的原因.有什么不同?以及kotlin委托如何有用?请给我一个工作实例来比较多态方法.
还要记住,您不仅限于一名代表。Kotlin 实现委托的方式类似于traits在 Groovy 等语言中的实现。您可以通过委托组合不同的功能。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()
}
Run Code Online (Sandbox Code Playgroud)
输出:
printed marks
calculated and printed totals
printed csv marks
calculated and printed higher totals
Run Code Online (Sandbox Code Playgroud)
你不能用继承来做到这一点。
它对于创建装饰器和对象组合非常有用。Joshua Bloch 在《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.
}
}
Run Code Online (Sandbox Code Playgroud)
代表团:
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
}
}
Run Code Online (Sandbox Code Playgroud)
它很有用,因为委托模式的大多数行为可以与delegation(b)的目标相同,但您只想覆盖方法的子集以采取不同的行为.
一个示例是一个InputStream实现,它将所有工作委托给另一个,InputStream但会覆盖该close()方法以不关闭底层流.这可以实现为:
class CloseGuardInputStream(private val base: InputStream)
: InputStream by base {
override fun close() {}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
634 次 |
| 最近记录: |