Groovy Traits vs. Mixins(@Mixin)vs. Delegates(@Delegate)を使用するタイミングを誰かが説明しますか?いくつかのトレードオフと設計上の懸念が役立つかもしれません。
それらはすべて、動作の複数の「クラス」を再利用できるように思われます。ありがとう。 :-)
このSOスレッドも参考になりました: @ Delegateと@Mixinの違いAST Groovyの変換
私は同意しますが、それらはすべて、複数の「クラス」の振る舞いを再利用できるようです。ただし、違いがあり、これらを理解することがおそらくあなたの決定に役立ちます。
各機能の簡単な要約/ハイライトと適切な使用例を提供する前に、それぞれの結論について要約しましょう。
結論/典型的な使用法:
それでは、これらのそれぞれについてもう少し詳しく見ていきましょう。
@デリゲート
多くの場合、継承は使いすぎです。つまり、しばしば不適切に使用されます。 Javaの古典的な例は、入力ストリーム、リーダー、またはコレクションクラスを拡張しています。これらのほとんどについて、継承の使用は実装と密接に結びついています。パブリックメソッドの1つは実際に別のメソッドを使用します。両方をオーバーライドし、super
を呼び出すと、望ましくない副作用が発生する可能性があります。同様に。
代わりに、 composition over inheritance の使用に努める必要があります。
例、リストに追加された要素をカウントするカウントリスト:
_class CountingList<E> {
int counter = 0
@Delegate LinkedList<E> list = new LinkedList<>()
boolean addAll(Collection<? extends E> c) {
counter += c.size()
list.addAll(c)
}
boolean addAll(int index, Collection<? extends E> c) {
counter += c.size()
list.addAll(index, c)
}
// more add methods with counter updates
}
_
この例では、_@Delegate
_は、「そのまま」残したいすべてのパブリックメソッドの退屈なボイラープレートコードをすべて削除します。つまり、呼び出しを基になるリストに単に転送するメソッドが追加されます。さらに、CountingList
は実装から分離されているため、これらのメソッドの一方が他方を呼び出して実装されているかどうかを気にする必要はありません。上記の例では、LinkedList.add(Collection)
がLinkedList.add(int, Collection)
を呼び出すため、実際にそうなります。したがって、継承を使用して実装するのは簡単ではありません。
概要:
@Delegate
_ sを追加できます。CountingList
)は、デリゲートクラスのインスタンスではありません。CountingList
はLinkedList
のインスタンスではありません。@ Mixin
_@Mixin
_変換は、今後の特性のサポートにより、groovy 2.3で非推奨になります。これは、_@Mixin
_でできることはすべて、代わりにtraitでできるべきであるというヒントを提供します。
私の経験では、_@Mixin
_は一種の混合的な祝福です。 :)
それは、コア開発者の承認により、「解決が難しい」バグに悩まされています。それは、それが「役に立たない」と言っているわけではありません。しかし、groovy 2.3を使用する(または待つ)機会がある場合は、代わりにtraitsを使用する必要があります。
AST変換が行うことは、あるクラスのメソッドを別のクラスに追加することです。例えば:
_class First {
String hello(String name) { "Hello $name!" }
}
@Mixin(First)
class Second {
// more methods
}
assert new Second().hello('Vahid') == 'Hello Vahid!'
_
概要:
Second
はFirst
のインスタンスではありませんランタイムミックスイン
ランタイムミックスインと_@Mixin
_トランスフォームはまったく異なり、異なるユースケースを解決し、まったく異なる状況で使用されます。それらは同じ名前を持っているので、一方を他方と混同したり、それらが同一であると考えるのは簡単です。ただし、ランタイムミックスインは、groovy 2.3で非推奨ではありません。
JDKのクラスなど、既存のクラスにメソッドを追加する方法として、ランタイムミックスインを考える傾向があります。 GroovyがJDKに追加のメソッドを追加するために使用するメカニズムです。
例:
_class MyStringExtension {
public static String hello(String self) {
return "Hello $self!"
}
}
String.mixin(MyStringExtension)
assert "Vahid".hello() == 'Hello Vahid!'
_
Groovyには、Mixinを手動で実行する必要のないNice extension module 機能もあります。代わりに、groovyは、クラスパス内の正しい場所でモジュール記述子を検出する限り、それを行います。
概要:
特徴
特性はgroovy 2.3の新機能です。
私はこれらの特性を、馴染みのあるインターフェースとクラスの間の何かと見なす傾向があります。 「軽量」クラスに似たもの。これらは、ドキュメントでは「デフォルトの実装と状態を持つインターフェース」と呼ばれています。
特性は、それらが置き換える_@Mixin
_変換に似ていますが、より強力です。まず第一に、それらはより明確に定義されています。特性は、インターフェイスのように直接インスタンス化することはできません。実装クラスが必要です。また、クラスは多くの特性を実装できます。
簡単な例:
_trait Name {
abstract String name()
String myNameIs() { "My name is ${name()}!" }
}
trait Age {
int age() { 42 }
}
class Person implements Name, Age {
String name() { 'Vahid' }
}
def p = new Person()
assert p.myNameIs() == 'My name is Vahid!'
assert p.age() == 42
assert p instanceof Name
assert p instanceof Age
_
特性と@Mixinの直接の違いは、trait
は言語キーワードであり、AST変換ではありません。さらに、クラスによって実装される必要がある抽象メソッドを含むことができることです。さらに、クラスはいくつかの特性を実装できます特性を実装するクラスは、その特性のインスタンスです。
概要: