2017-05-28 11 views
5

私はコットンの代表団について本当に混乱しています。ここでは、kotlinの相違と同じように見える、通常の多型アプローチを説明しましょう。kotlinの委任はどのように便利ですか?

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 
} 

私は指定されたクラスのオブジェクトのメソッドを呼び出すためにb変数にBaseインタフェースの実装クラスを渡すことができます。それでは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はそれを導入したのです。違いはなんですか?コトリンの代表団がどのように役立つのでしょうか?多型アプローチと比較するための実例を私にお願いします。

+0

これは、Kotlinがそれを実装する方法よりも、委任そのもののメリットについての質問であるかどうか疑問です。 –

+0

私はコットリン代表団がどのように役立つのか知ってもらいましたか?委任がどのように役立つかではありません。私はすでに委任の目的について知っているからです。しかし、kotlinの実装は私を混乱させています。 – UnKnown

+0

コードの最初のブロックは、2番目のブロックと同等の結果を返しません。手で 'Derived 'を実装しようとすると、違いを感じるでしょう。 – Ilya

答えて

4

はまた、あなただけの1デリゲートに限定されていないことを覚えておいてください。 Kotlinが委譲を実装する方法は、Groovyのような言語でtraitsの実装と似ています。代理人を介して異なる機能を構成することができます。 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() 
} 

出力:

printed marks 
calculated and printed totals 
printed csv marks 
calculated and printed higher totals 

あなたが継承してこれを行うことはできません。

5

ほとんどの動作が委任先(b)のターゲットと同じになることがありますが、異なる方法で動作するメソッドのサブセットをオーバーライドしたい場合は、Delegation Patternが役に立ちます。

例はInputStreamの実装であり、すべての作業を別のInputStreamに委任しますが、close()のメソッドをオーバーライドして基本ストリームを閉じません。

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

を試してみてください。インターフェイスの多態性の方法でその例を比較できます。私は委任が有用だと知っていますが、kotlinのことはどうですか? – UnKnown

+0

mainメソッドで上記のコードを呼び出すことはできますか?だからインタフェース多型の例と比較できますか? – UnKnown

3

デコレータの作成やオブジェクトの作成に非常に便利です。 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. 
    } 

} 

委任:

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'を内部的に呼び出すことでした。継承 - 例では、 'add()'をオーバーライドしているため、すべての項目に対して「all added」と「xy」を追加します。 Delegationの例では、addAllは 'add'を呼び出すのではなく、MutableListの' add'を呼び出すため、「added all」を得るだけです – D3xter

関連する問題