2012-04-26 6 views
2

List<ClassA>またはList<ClassB>のように動作するgeneric listを作成する必要があります。これは次のような状況があるためです。Java方法:汎用リストの作成?

if(e instanceof A) 
return A; 
else 
return B 

しかし、私は、List<ClassA> ResultまたはList<ClassB> Resultいずれかとして機能することができ1 List Resultを移入したい私たちはここにジェネリックを使用することができます確信しているが、私はそれを使用する方法がわかりませんか?

更新

私がやりたいすべては、そのランタイムです、私のリストには、適切なタイプで占め、いずれかclass A or class B

if() 
{ 
    //data is present in List<ClassA> classAList = new ArrayList<ClassA>(); 
    //return classAList 
} 
else 
{ 
    //return List<ClassB> classBList = new ArrayList<ClassB>(); 
} 

・ホープ、このことができますする必要があります。

+5

は、相互に関連する 'ClassA'と' ClassB'ていますか? – birryree

+0

リストは既に一般化されています。 ClassAオブジェクトまたはClassBオブジェクトだけを含むリストが必要な場合は、両方を含む 'List 'を使用して、 'instanceof'を使用してそれぞれのタイプを判断することができます。 – Neil

+0

ジェネリックの全体のポイントはタイプ_セーフである - 変更できるタイプを持たないことです。 – SLaks

答えて

2

あなたが正しく理解していれば、指定されたオブジェクトがClassAかClassBかに応じて、ClassAのリストまたはClassBのリストを作成できます。

public List<? extends Object> getList(Object e) { 
    List<? extends Object> list = new ArrayList<? extends Object>(); 
    if(e instanceof ClassA) { 
     List<ClassA> listA = new ArrayList<ClassA>(); 
     // Populate list somehow 
     list = listA; 
    } else if (e instanceof ClassB) { 
     List<ClassB> listB = new ArrayList<ClassB>(); 
     // Populate list somehow 
     list = listB; 
    } 
    return list; 
} 

残念ながら、戻り値の型は(あなたが代わりに別の戻り値の型を持つ2つのメソッドを作成することができますが、彼らは別の名前を持っている必要があります)のいずれかのタイプのために許可する必要があります。しかし、これにより、listAとlistBをより一般的なリストに割り当てる前に独自の型として使用することができます。

しかし、これはそれほど選択肢があるかもしれない、SOLID principalの違反です:役に立てば幸い

public abstract class Root<T> { 
    public abstract List<T> getList(); 
} 

public class ClassAList extends Root<ClassA> { 
    @Override 
    public List<ClassA> getList() { 
     List<ClassA> list = new ArrayList<ClassA>(); 
     // Populate list somehow 
     return list; 
    } 
} 

public class ClassBList extends Root<ClassB> { 
    @Override 
    public List<ClassB> getList() { 
     List<ClassB> list = new ArrayList<ClassB>(); 
     // Populate list somehow 
     return list; 
    } 
} 

!このような

+0

これは効率的なやり方ですか?/ – Rachel

+0

List <?のようなことをしていることに躊躇していますか?オブジェクトを拡張する> '、なぜわからない...それは私に害を及ぼすかどうか? – Rachel

+0

それはあなたが意味するものであればそれほど遅くはありませんが、オブジェクトのタイプを確認することは、私の答えをデモするために更新したのでベストプラクティスではありません。 'List <? extends Object> 'は単にそれが" Object "クラスを拡張するオブジェクトのリストであることを意味します。それはObjectではありません。 – Neil

0

ClassAとClassBが共通の基本クラスを持つ場合(つまり、両方が同じクラスを拡張する場合)、汎用クラスのパラメータで基本クラス型を使用できます。

+0

いいえ、基本クラスはありません。 – Rachel

+0

@Rachel ClassAとClassBを共通の基盤となるように再設計することは可能ですか?もしそうでなければ、上記のバーナードの答えが働くかもしれない。 – kevin628

0

ジェネリックは基本的には静的な時間チェック用です。あなたのケースでは、あなたがデータの2種類を持っているので、ジェネリックを使用すると、共通の祖先クラスが

+0

ここに私のオプションは何ですか? – Rachel

+0

リストを使用する ControlAltDel

1
class A extends C{ ... body ... } 
class B extends C{ ... body ... } 

//動作します& Bシェアしない限り、任意の意味をなさない

List<C> list = new ArrayList<C>(); 
list.add(new A()); 
list.add(new B()); 

Bernardの提案

概要:

あなたのオプションは、親クラスを作成することのいずれかであります親クラスをAとから拡張し、親タイプをリストに追加するか、またはインターフェースを作成し、ABからインターフェースを実装し、インターフェース・タイプをリストに入れます。いずれにしても、クラスを変更することになりますAB新しいインターフェイスまたはクラスを作成する

+0

クラスAとクラスBが拡張されているクラスCがありません – Rachel

+1

@Rachelあなたのオプションは、親クラスを作成し、親クラスを 'A'と' B'から拡張するか、あるいはインターフェイスを作成します。 'A'と' B'のインタフェースを実装し、インタフェースの型をリストに入れてください。いずれにせよ、あなたはクラスAとBを変更することになります。 – ant

+0

もちろん、すべてのクラスは 'Object'から拡張されます – newacct

1

両方のクラスが実装する共通のインターフェイスを使用する必要があります。あなたのインターフェイスがMyInterfaceと呼ばれているとします。どちらのクラスもこのインタフェースを実装でき、genericリストはList<MyInterface>のタイプになります。

代わりに、両方のクラスに共通の基本クラスがあることです。

編集:OPによって要求された

は、いくつかの例を追加しました。

例インタフェース:

public interface MyInterface 
{ 
    String getName(); 

    void setName(String name); 
} 

例インタフェースの実装:

public class ClassA implements MyInterface 
{ 
    private String name; 

    public String getName() 
    { 
     return name; 
    } 

    public void setName(String name) 
    { 
     this.name = name; 
    } 
} 

例ジェネリックリストの使い方:

List<MyInterface> list = new ArrayList<MyInterface>(); 

list.add(new ClassA()); 

MyInterface item = list.get(0); 

item.setName("Bob"); 

String name = item.getName(); 
+0

彼らは共通のクラスを持っていません。 – Rachel

+0

@Rachel:両方のクラスが実装するインターフェイスを使用します。 – Bernard

+0

サンプルインターフェイスを1つしか持たず、そこからすべてを拡張しようとします。 – Rachel

0

いずれかClassAClassBのためになる、これを行うための唯一の方法共通の親クラスを持つか、または共通インタフェース。どちらの場合でも、リストを特定のクラスに限定する唯一の方法は、その共通の親または共通のインターフェースを持つ他のクラスがない場合です。

これらのいずれも、共通のこの共通のインターフェイスが既に存在するか、またはClassAおよびClassBを制御する必要があります。彼らがしていないし、しない場合は、あなたがしているものを行う方法はありません。

+0

現在、私は共通のクラスを持っていないか、私は共通のインターフェイスを持っていません – Rachel

+0

@Rachel:クラスを制御できますか? –

+0

まあ、私はそれらを変更することができます...実際に他の開発者がそれを開発しました – Rachel

0

これは、ABが共通の親を共有する場合(Cなど)にのみ可能です。その後、List<C>を返すことができます。

List<Object>を返すことはできますが、これに対して助言してデザインを再検討することをおすすめします。

+0

あなたの提案は何ですか – Rachel

+0

@Rachelそれは呼び出し元のコードが何をしているかによって異なります。おそらく 'E 'の可能なクラスごとに異なるメソッドを作るでしょう。 – Jim

0

何かは、おそらく:彼らは同じインターフェイスまたは親クラスを共有のように

public class Test { 
    static class A {} 
    static class B {} 
    private static List<?> getList() { 
    List<A> aList = new ArrayList<A>(); 
    List<B> bList = new ArrayList<B>(); 
    aList.add(new A()); 
    if (aList.size() > 0) { 
     return aList; 
    } else { 
     return bList; 
    } 
    } 

    public static void main(String[] args) { 
    List<?> cList = getList(); 
    System.out.println(cList); 
    } 
} 
関連する問題