web-dev-qa-db-ja.com

MixinをJavaに実装しますか?

Java 6を使用すると、 mixin をどのように実装できますか?Rubyでは非常に簡単で可能です。Javaで同様に取得するにはどうすればよいですか?

55
Lennie

そのために [〜#〜] cglib [〜#〜] を使用できます。クラス Mixin は、いくつかのインターフェイス/オブジェクトデリゲートから動的クラスを生成できます。

static Mixin    create(Java.lang.Class[] interfaces,
                        Java.lang.Object[] delegates)
static Mixin    create(Java.lang.Object[] delegates)
static Mixin    createBean(Java.lang.Object[] beans) 
21
Daniel Fanjul

オブジェクト構成だけを使用すると思います。新しい機能を投入するたびに、別のオブジェクトをメンバーとしてクラスに作成します。すべての混合クラスを同じタイプにしたい場合は、配列をメンバーオブジェクトとして使用して、各要素が他のすべての要素で構成され、特定の要素にディスパッチできます。

13
Martin

デフォルトのメソッド

Java 6ですが、Java 8の場合、かなりまともな代替案があります デフォルトのメソッド

インターフェースメソッドの「デフォルト」実装を追加できるため、インターフェースを実装するすべてのクラスを壊すことなく、新しいメソッドを追加できます。

ミックスインが状態を必要としない限り、インターフェースでコードを書くことができます。そうすれば、クラスはこれらのインターフェースを必要なだけ実装して、ブームにすることができます あなたはミックスインを持っています

これはシステムの乱用ですか?少しですが、状態がないため、多重継承の問題にはなりません。

もちろん、これもこのアプローチの最大の欠点です。

13
Brad Cupit

Javaは単一継承のみをサポートしているため、これは不可能です。 WP:Mixin を参照してください。

[〜#〜] edit [〜#〜]:インターフェースに関するコメントのため:ミックスインの優れた点は、それらを記述せずに結合できることです組み合わせのコード。インターフェイスを使用すると、組み合わせの機能を自分で実装する必要があります(拡張できる1つのクラスを除く)。

8
Johannes Weiss

最も簡単な方法は、静的インポートを使用することです。クラスの一部のように見えますが、実際には他の場所で定義されているコードの再利用が可能です。

長所:

  • 本当に簡単
  • 静的インポートを好きなだけ「ミックスイン」できます

短所:

  • 静的メソッドは 'this'にアクセスできないため、手動で渡す必要があります
  • 状態なし:静的メソッドは独自のインスタンスフィールドを持つことができません。独自の静的フィールドのみを定義でき、静的フィールドを呼び出すオブジェクトによって共有されます。
  • クライアントクラス(コードが混在しているクラス)でパブリックメソッドを定義できません。 Rubyでは、ミックスインをインポートすると、これらのパブリックメソッドがクラスのパブリックメソッドとして実際に定義されます。この場合、Javaでは継承がより良い解決策になります(複数のクラスを拡張する必要がない場合)

例:

import static my.package.MyHelperUtility.methodDefinedInAnotherClass;

public class MyNormalCode {
    public void example() {
        methodDefinedInAnotherClass();
    }
}
7
Brad Cupit
5
Ray Tayek

Rubyミックスインは、Java抽象クラスと同等です。いいえ、Javaでミックスインを実装することはできません。インターフェースを使用することで近づくため、ミックスインでコードをまったく定義しませんが、Rubyミックスインの場合と同じ動作を直接達成することはできません。

5
Eddie

更新:Qi4jはApache Polygeneになりました https://polygene.Apache.org

Qi4jのMixinsの定義は、基本クラスから始まっていないため、おそらく非常にユニークです。その極端に行くと、アプリケーションの構築方法のまったく新しいパラダイムが出現し、それを複合指向プログラミングと呼びます。コンポジットは同等の「オブジェクト」であり、Mixinsが一緒に配線されているだけでなく、制約(検証)、懸念(アドバイス周辺)、SideEffects(メソッドの結果を変更することはできません)も含まれます。

Qi4jには非常に強力なMixinストーリーがあると思います。ミックスインは「タイプ」または「ジェネリック」にすることができ、パブリック(コンポジット外部からアクセス可能)または純粋にプライベート(コンポジット内部)にすることができます。 Qi4jはプロパティとは何かを強力​​に定義し、永続性が組み込まれています。これにより、ストレージ実装がドメインにリークされません(警告、Qi4jがドメインにリーク)。そして、永続化されたエンティティがいったん登場すると、関連付けの強力な定義も必要になります(Qi4jに含まれます)。

概要については http://www.qi4j.org/state-modeling.html を参照してください。

Qi4jでは、Mixinsのみが状態を持ちます。 Constraints/Concerns/SideEffectsは状態を持つことができません(それらが存在する場合、プライベートミックスインを参照する必要があります)。

Qi4jでコンポジットを定義するには、型自体で構造的に行うか、OR at bootstrap time at the runtime model is created。

構造的に;


@Mixins({PetrolEngfineMixin.class, FourWheelsMixin.class})
public interface Car extends HasEngine, HasWheels, EntityComposite
{}

起動時;


public interface Car
{}


public class CarModuleAssembler implements Assembler { public void assemble( ModuleAssembly module ) { module.entities( Car.class ) .withMixins( PetronEngineMixin.class, FourWheelsMixin.class ); } }

しかし、これはQi4jの機能の表面に触れているだけです。

5
Niclas Hedhman

http://code.google.com/p/javadude/wiki/AnnotationsMixinExample を確認してください。

私が作成した一連の注釈を使用しています。

注:私は、いくつかのAPIの破損を含む、アノテーションのメジャーアップデートに取り組んでいます。今後数週間で新しいバージョンをリリースする予定です。

4

探しているミックスインの機能が正確にわからない場合でも、デコレータパターンを使用してその多くを実行できます。

http://en.wikipedia.org/wiki/Decorator_pattern#Java

2
Lewis Diamond

JavaでMixinsを実行できます(つまり、5、6、7) AspectJ ITDs を使用します。 Java 8はもちろん、ディフェンダーメソッドでより優れた機能を追加します。

2
Adam Gent
2
TofuBeer

私は this があなたの質問に答えることがあると思います...私は完全ではありませんが ミックスインがまだ何であるかを理解していることを確認してください...

1
leeand00

私はこれをJava 7.に提供することを検討しています。最初のカットは、この記事に示されている例を使用することです。

Java 6で動作するはずです。これは上記の他のインジェクションオプションと同様です。C#およびRubyでのMixinsの私の経験に基づいて、エミュレートまたは偽造するだけでなく、mixinの実装を目指す必要がありますそれ。

別のモデルは、 Jackson で使用されるモデルです。

新しいJava 8リリースを使用できる場合、たとえばプレリリースモードの場合は、それが役立つ場合があります。

'be-a'ミックスインする労力を必要とする仮想拡張メソッドを使用します。だから私の心の中でそれはまだ初期の段階であり、私は最初のリンクによって提供されるよりクリーンに見えるアプローチ(または同様のもの)を好みます。

1
will

はい、Java=でミックスインアプローチを実装する最も簡単で便利な方法は、静的メソッドを含むクラスからの静的インポートを使用することです。

1
SergeZ

古い質問への答え。

Apache Zestを調べました。多分それは私だけだったかもしれませんが、例は少し面倒です。そして、私はポイントをかなり得ることができませんでした。別の方法として、オブジェクトチームがあります。

しかし、私はあなたがこのレポを見ることを勧めます:

https://github.com/Mashashi/javaroles/

それはあなたがしたいことを部分的にカバーするかもしれません。簡単そうです。

次に例を示します。

ロールのインターフェースの定義:

public interface Human {
String hello(); 
String die(String age);  
String eat();
String dance();
}

public interface Monkey {String hello(); String eat();}

リジッドタイプのAnimalRolesを定義しています...

public class AnimalRoles implements Human, Monkey{

public static final String HALLO = "Default hallo";
public static final String DIE = "Default they kill me...";
public static final String EAT = "Default eat...";

@ObjectForRole public Human human;

@ObjectForRole public Monkey monkey;

public AnimalRoles(Human human, Monkey monkey){
    this.human = human;
    this.monkey = monkey;
    if(this.human!=null){
        ((Portuguese)this.human).core = this;
    }
}

@Override
public String hello() {
    return HALLO;
}

@Override
public String die(String age) {
    return DIE+age;
}

@Override
@TurnOffRole
public String eat() {
    return EAT;
}

@Override
public String dance() {
    return "Just dance";
}

public String notInRole(){
    return "Oh oh";
}
}

クラスの役割Bonoboを定義しています...

public class Bonobo implements Monkey{
public Bonobo() {}

@Override
public String hello(){
    return "Ugauga";
}

@Override
public String eat() {
    return "Nhamnham";
}

}

クラスの役割ポルトガル語を定義しています...

@RoleObject(types = { AnimalRoles.class })
public class Portuguese implements Human{

public static final String HALLO = "Hey there";
public static final String DIE = "They killed me";
public static final String EAT = "Eating boiled pork now";

public AnimalRoles core;

public Portuguese() {}

@Override
public String hello() {
    return HALLO;
}

@Override
public String die(String age) {
    return DIE+age;
}

@Override
public String eat() {
    return EAT;
}

@Override
public String dance() {
    return core.dance()+" modified!";
}

}

テストを実行しています...

new RoleRegisterComposition().registerRools();
AnimalRoles a = new AnimalRoles(new Portuguese(), new Bonobo());
System.out.println(a.hello());
System.out.println(a.dance());

印刷します...

"Hey there"
"Dance modified!"
0
skynetDude

純粋なJava cglibを使用してミックスインを作成する方法を示す小さなデモプロジェクトをご覧ください。主にそれはプロキシジェネレーターへの呼び出しにすぎません。これは味方です。この例にはjunitテストケースが含まれていますプロキシをインスタンス化する方法を示します。

https://github.com/literadix/JavaMixins

0

「Mixin」という用語は、アスペクト指向プログラミング運動におけるJava用語「aspect」と同等ではありませんか?AspectJはおそらく一見の価値があります。

0
LeeGee