2017-05-28 93 views
5

我真的很困惑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 
} 

我知道这是两个代码工作正常的简单场景。这应该是委托的好处,这就是科特林介绍它的原因。有什么不同?科特林代表团如何有用?请给我一个工作示例,以便与多态性方法进行比较。

+0

我不知道这是一个更多关于代表团本身优点的问题,而不是Kotlin如何实现它。 –

+0

我问它知道科特林代表团有用吗?不是代表团如何有用。因为我已经知道授权目的。但kotlin的实施让我感到困惑。 – UnKnown

+0

第一个代码块没有给出与第二个相同的结果。试着手工实现'派生',你会感受到不同。 – Ilya

回答

4

还记得,你不再仅仅限于一个代表。 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 

你不能继承做到这一点。

5

这很有用,因为Delegation Pattern其中大部分行为可以与委派的目标相同(b),但您只是想重写方法的子集以采取不同的行为。

一个示例是InputStream实现,该实现将所有工作委托给另一个InputStream,但覆盖close()方法以不关闭底层流。这可以实现为:

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

你可以给测试的例子吗?所以我可以用接口多态的方式比较这个例子。我知道代表团很有用,但kotlin的代表如何? – UnKnown

+0

你可以在主要方法中调用上面的代码。所以我可以比较接口多态性的例子? – UnKnown

3

这对于创建装饰器和对象组合非常有用。 Joshua Bloch在Effective Java中的第2版第16项'Favor Composition Over Inheritance'显示了一个很好的例子:继承很容易破解,而装饰器不是。

继承:

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 
    } 

} 
+0

我仍然可以调用内部没有':MutableList 委托''你能给我工作的例子吗?所以我可以比较多态方法。 – UnKnown

+0

我认为你应该详细阐述你的例子,以便你可以证明这是如何被证明是“非常有用”的。恐怕不像你似乎表示的那么明显。 –

+1

首先,这是一个工作示例,只需复制并粘贴到try.kotlinlang.org并试用即可。第二:Miha的意思是,addAll'在内部调用每个新项目的“add”。所以在继承的例子中,你会得到“全部添加”,然后为每个项目“添加xy”,因为我们重写'add()'。在代表团的例子中,你只能“添加所有”,因为addAll不会调用我们的“add”,而是调用MutableList的“add” – D3xter