4

Javaでは、特定のタイプ(たとえば)の配列を意味するジェネリックテンプレートを探していますFoo。これにより、配列に対するインスタンスメソッドの呼び出しが可能になります。舞台裏では、これは、配列内のすべてのFooインスタンスを反復処理し、各インスタンスでインスタンスメソッドを呼び出すことを意味します。

おそらく、いくつかのコードはこの点をよりよく示しています:

public class Foo{

   public Foo(){}

   public void Method1(){}

}

だからあなたは持っています:

Foo foo = new Foo();
foo.Method1();

しかし、本質的にこの種のことを可能にしたカスタムタイプの汎用テンプレートを作成できますか?

Foo[] foos = new Foo[]{new Foo(),new Foo(), new Foo()};
foos.Method1();

これは本質的に次の構文糖衣です:

foreach(Foo f : foos){
  f.Method1();
}

私の動機は、誰かが次のようなvarargsを使用できるようにすることです。

someHelper(fooInstance1,fooInstance2).Method1()

を返しsomeHelper()ますFoo[]

Method1()呼び出しが値を返した場合、これを戻り値の配列(ここでReturnVals.size == Foos.size)にラップするとさらに良いでしょう。

最悪の場合、これを実現するために、この作業が必要なタイプごとに個別のクラスを作成する必要があります。おそらく、インターフェイスを使用して、単一のインスタンスとインスタンスの配列に適用される機能を記述します。

これをエレガントに実現できるJavaマジック、デザインパターン、またはジェネリックジゲリーポケリーはありますか?

さらに、そうでない場合、どの言語もこれを本質的に促進しますか?

すべてのシナリオで機能するとは限らないことを感謝しますが、それは私が推測するプログラマーの裁量によるものです。

どうもありがとう

4

5 に答える 5

1

複合パターンを求めています。プロジェクトPerfectJPatternには、コンポーネント化された汎用で再利用可能な実装があります。コンポジットのドキュメントページと、GoFブックのと一致する例を確認してください。

例の関連部分の逐語的なコピー。たとえば、IGraphicインターフェイスと、RectangleやLineなどのいくつかの実装がある場合、次のことができます。

// build the composite
IComposite<IGraphic> myComposite = new Composite<IGraphic>(IGraphic.class);
myComposite.add(new Rectangle());                
myComposite.add(new Line());
myComposite.add(new Line());

// use the composite, invokes the IGraphic#draw() in the 
// underlying Rectangle and two Line instances
myComposite.getComponent().draw();

これは、特定のケースでどのように機能するかです。

Foo fooInstance1 = new Foo();
Foo fooInstance2 = new Foo();
IComposite<Foo> myComposite = new Composite<Foo>(Foo.class);
myComposite.add(fooInstance1);    
myComposite.add(fooInstance2);    
// invokes Method1 on instance1 and instance2 transparently
myComposite.getComponent().Method1();

// alternatively do
Foo myCompositeFoo = myComposite.getComponent();
// pass this myCompositeFoo around and do
myCompositeFoo.Method1();

IComposite再利用可能な実装は実際のコンポジットを保持し、インターフェースを実装/提供するのではなくFoo、メソッドを介してそれを取得する必要があることに注意してくださいgetComponentCompositeこれは小さな厄介な問題であり、Javaには、任意の静的に未知のインターフェースを実装する何か(この場合)のインスタンスを作成する他の方法がないために必要です。私ができる最善のことは、Compositeその下に真の複合コンポーネントを構築し、目的のインターフェイスタイプを返すことですFoo。これは動的プロキシを使用して実装されますが、実装はタイプセーフで完全にコンポーネント化されています。つまり、インターフェイスを実装する新しいコンポジットアレイを作成する必要はありません。

于 2012-12-06T12:38:57.053 に答える
1

あなたは反射でこれを行うことができます。

実行時にTのすべてのパブリックメソッドを調べ、同じシグネチャと、すべてのオブジェクトをループして同じメソッドを呼び出す本体を持つメソッドをそれ自体に挿入するジェネリッククラスを作成します。

これに伴う問題は、動的に作成されたメソッドを呼び出す方法です。これはリフレクションを介してのみ可能であるため、元のコードでのメソッド呼び出しはリフレクションを介して実行する必要があることを意味します。

于 2012-12-06T12:29:51.713 に答える
1

これを行うにはさまざまな方法がありますが、ほとんどの場合、ラッパーオブジェクトなどを使用します。ただし、目的のタイプがインターフェイスである場合は、運が良ければ、動的プロキシを使用して実際に実行できます。

例えば

public static void main(String[] args) throws IOException {
    B[] objs = {new B(), new B(), new B()};
    A oneForAll = createMulticastObject(objs, A.class);
    oneForAll.print();
}

@SuppressWarnings("unchecked")
public static <T, U extends T> T createMulticastObject(final U[] targets, Class<T> interfaceClass) {
    return (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class<?>[] {interfaceClass}, new InvocationHandler() {

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            Object ret = null;
            for (U target : targets) {
                ret = method.invoke(target, args);
            }
            return ret;
        }
    });
}


interface A {
    void print();
}

static class B implements A {
    @Override
    public void print() {
        System.out.println("Invoked.");
    }
}

明らかな制限は次のとおりですA(つまり、マルチキャストメソッド呼び出しで使用するオブジェクトのタイプはインターフェイスである必要があります。

もう1つの明らかな制限は、マルチキャストオブジェクトは、これらすべての呼び出しから1回のリターンしか返すことができないことです。

コードがすべて1つの場所にあると見苦しく見えるかもしれませんがcreateMulticastObject、メソッドはユーティリティメソッドとして使用できるメソッドでありABとにかくすでに記述されています。したがってdynamic proxies、通常のラッパーなどを次のように減らします。

A oneForAll = createMulticastObject(objs, A.class);

于 2012-12-06T13:02:43.267 に答える
0

これをエレガントに実現できるJavaマジック、デザインパターン、またはジェネリックジゲリーポケリーはありますか?

実際にはそうではありません-多くの定型文がないわけではありません。つまり、自分でダムループを作成するコードが少なくなります。

さらに、そうでない場合、どの言語もこれを本質的に促進しますか?

ほとんどの機能的な言語は、そのようなものをサポートしています。Scalaでは、次のことができますfoos.foreach(_.Method1())。ここで、foreachはすべての要素でコードブロックを呼び出すメソッドであり、アンダースコアは現在の要素のエイリアスです。実行可能なコード:http://ideone.com/QRtPlK

Java 8では、コレクションのストリームビューをメソッド参照とともに使用して、次のようなことを行うことができます。

foos.stream().forEach(Foo::method1);
于 2012-12-06T13:31:59.587 に答える
0

apachesのCollectionUtilsのメソッドを見てください。リストで呼び出すメソッドごとにインターフェースを実装する必要があります。

例:

CollectionUtils.collect(foos, new Transformer() {
    public Object transform(Object foo) {
        return ((Foo) foo).method();
    }
});

ここでは任意のクラスを使用しましたが、別のクラスにTransformerを実装して再利用することもできます。

ジェネリックスのバージョンが存在するかどうかはわかりません。

機能的な言語(scala、haskell、…)も試してみてください。彼らはこの種のことを非常に簡単にします。

于 2012-12-06T12:31:23.860 に答える