我对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委托如何有用?请给我一个比较多态方法的工作实例。
答案 0 :(得分:5)
它很有用,因为Delegation Pattern大部分行为可以与委托目标(b
)相同,但您只想覆盖方法的子集以采取不同的行为。
一个示例是InputStream
实现,它将所有工作委托给另一个InputStream
,但会覆盖close()
方法以不关闭基础流。这可以实现为:
class CloseGuardInputStream(private val base: InputStream)
: InputStream by base {
override fun close() {}
}
答案 1 :(得分:4)
另请记住,您并不仅限于一名代表。 Kotlin实现委派的方式类似于Groovy等语言中的traits
实现。您可以通过代表组合不同的功能。 Kotlin的方式也可以被认为更强大,因为你可以插入&#34;插入&#34;不同的实现方式。
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
你不能通过继承来做到这一点。
答案 2 :(得分:3)
它对于创建装饰器和对象组合非常有用。 约书亚布洛赫在有效的Java,第2版,第16项&#39;赞成组合而不是继承&#39;显示了一个很好的例子:继承很容易破坏,而装饰则不是。
继承:
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
}
}
答案 3 :(得分:0)
以下为示例:-
interface Mode{
val color:String
fun display()
}
class DarkMode(override val color:String) : Mode{
override fun display(){
println("Dark Mode..."+color)
}
}
class LightMode(override val color:String) : Mode {
override fun display() {
println("Light Mode..."+color)
}
}
class MyCustomMode(val mode: Mode): Mode{
override val color:String = mode.color
override fun display() {
mode.display()
}
}
现在,自定义模式可以重用display()
和DarkMode
两种模式的LightMode
功能
fun main() {
MyCustomMode(DarkMode("CUSTOM_DARK_GRAY")).display()
MyCustomMode(LightMode("CUSTOM_LIGHT_GRAY")).display()
}
/* output:
Dark Mode...CUSTOM_DARK_GRAY
Light Mode...CUSTOM_LIGHT_GRAY
*/
Kotlin本机支持委托模式。 Kotlin提供了by关键字来指定我们的自定义模式将委托给的委托对象。 我们可以使用关键字by来获得与上面代码相同的结果。
class MyCustomMode(val mode: Mode): Mode by mode
fun main() {
MyCustomMode(DarkMode("CUSTOM_DARK_GRAY")).display()
MyCustomMode(LightMode("CUSTOM_LIGHT_GRAY")).display()
}
/* output:
Dark Mode...CUSTOM_DARK_GRAY
Light Mode...CUSTOM_LIGHT_GRAY
*/