2012-01-03 21 views
7

私は私のバウンドの実装で使用するタイプの配列を取得するために変数の型引数を持つジェネリック

public interface Foo<R, P...> { 
    public R bar(P...) {/*misc*/} 
} 

のような何かをしたいです。これはJavaで可能ですか?

Varargsは、指定されたクラスの引数をいくつでも持つことができるように設計されています。

私のメソッドがいくつかの引数を受け取り、それぞれが与えられた異なるクラスのメンバであるようにするには、それを使用したいと思うでしょう。これらのクラスは、ジェネリックがバインドされるときに定義されます。

回避策がありますが、これを行うにはタイプセーフな方法がありますか?

+0

これまでのところ何が問題になっていますか?唯一の問題は、varagsがジェネリックでうまくいくわけではないということです。 –

答えて

7

あなたは明らかにbar異なる種類(何かがをするために使用さでない可変引数)の複数のパラメータを取る作ることができるようにしたいので、私はそれではなく、単一のパラメータを取る作ることをお勧めしたいです。その単一のパラメータを、使用する個々の「パラメータ」を保持するコンテナにすることができます。

一般に、このメソッドで使用するパラメータのセットごとにクラスを作成して、そのクラスに含まれる各オブジェクトに適切な名前を付けるのが最適です。ただし、ホルダーとして使用する一連のタプルタイプ(Pairなど)を作成するようなこともできます。ここで

は例です:

public class Foo<R, P> { 
    /* 
    * Not sure how you intend to provide any kind of implementation 
    * here since you don't know what R or P are. 
    */ 
    public R bar(P parameters) { ... } 
} 

public class SomeFoo extends Foo<SomeResult, Pair<Baz, Bar>> { 
    public SomeResult bar(Pair<Baz, Bar> parameters) { ... } 
} 

SomeFoo foo = ... 
SomeResult result = foo.bar(Pair.of(baz, bar)); 
+0

これは良いアイデアだと思います。バインディングクラスは、引数の数と型をコンテナ/タプルオブジェクトにラップすることで定義できます。タプル/ペアはコアライブラリ/ jdkの一部ですか?私はそれらを見つけることができませんでしたが、私は自分自身を書くことは自明ではないと思います。 Javaのタプルが構造体の役割を正確に果たすことを示唆するのは正しいでしょうか? –

+2

一般的に私はタプル型を作ることを避けます(JDKには存在しません。なぜなら、さまざまな理由でうまく動作しないためです)、それぞれのオブジェクトに有用な名前を付ける実際のクラスを作成するからです。私は主にそれについて言及しました。なぜなら、あなたが要求していたようだから、あなたが持っているオプションであるからです。短い答えは、任意の数の任意のタイプのオブジェクトをグループ化したい場合、クラスが行く方法です。あなたはクラスを非常に小さくてシンプルにすることができ、それは基本的に構造体として機能します。 – ColinD

+1

Eclipseには実際にこれを自動的に行う機能があります: 'refactor>パラメータオブジェクトを導入する' – AJMansfield

2

あなたが書いた:

を私はのメンバーである、それぞれが、私の方法は、いくつかの引数を受け入れる持っていること(または同様のもの)を使用したいですある異なるクラス。

私はそれはオブジェクトと一緒にクラスのインスタンスを含むように、いくつかの醜いハックせずに、タイプセーフな方法でこれを行うことは可能だとは思いません。

問題は、VarArgsでは実際に配列に渡されていることです。しかし、その中に異なるタイプのオブジェクトを持つ配列を持つことはできません。それらはすべて同じでなければなりません(またはサブクラスなので、X [] yなら各要素はXのサブクラスでなければなりません)

Ifあなたの関数は実際には、Tのインスタンスと一緒にClassのインスタンスを格納するクラスのようなものを作成することができる複数の型を扱うことができ、パスはそのコンテナのvar argsリストに入れます。

したがって、たとえば、あなたは

class TypedInstance<T>{ 
    Class<T> type; 
    T instance; 
} 

を持つことができ、その後

public whatever(TypedInstance<? extends Object>... whatever){ 
    ... 
    doSomethingWith(whatever[0].type, whatever[0].instance); 
    ... 
} 

ハックのこれらの種類があるため、Javaの型消去の必要があるようになります機能を持っています。ジェネリックパラメータは実行時に削除されるため、使用する場合は元に戻す必要があります。

+0

+1いい考えですが、関数はPを使用しません。オブジェクトを拡張する必要がある以外の型の型の安全性はありません。 'instance'の型はinstance.getClass()で取得できます。基本的にはタイプTのインスタンスをラッパーにラップしていますが、これは少し意味がありません。 –

+0

真実ですが、これを直接行う実際の方法はありません...ネストされたタプルを使用するというColin Dの考えはかなり鮮明ですが。 Scheme/lispでのやり方を思い出させます。 –

関連する問題