kotlin委托如何有用?

时间:2017-05-28 20:15:56

标签: 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代表团的好处是什么?其中描述了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委托如何有用?请给我一个比较多态方法的工作实例。

4 个答案:

答案 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)

以下为示例:-

enter image description here

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
 */