1

Javaジェネリック関連の質問があります

私は以下のように呼ばれる Parents クラスを持っていContainerます: コンテナは他のコンテナを含むことができますServices. Services クラスは Container を拡張しますが、Container も拡張するものだけServiceMembersを含めることができます。

Services クラスで親クラスのgetElements()メソッドをオーバーライドし、Container クラスのサブクラスでもある要素の ArrayList を返しても、以下のコードは機能しません。

これを機能させる方法についてのアイデアはありますか、それとも間違った方法で使用していますか?

public class Container
{
   protected ArrayList<Container> elements = new ArrayList<Container>();

   public ArrayList<Container> getElements()
   {
   }
}

public class Service extends Container
{
  public ArrayList<ServiceMember> getElements()
  {
  }
}
4

3 に答える 3

1

Services クラスで親クラスの getElements() メソッドをオーバーライドし、Container クラスのサブクラスでもある要素の ArrayList を返しても、以下のコードは機能しません。

これは正しくありません。タイプ消去 のため、メソッドArrayList<ServiceMember>のオーバーライドに必要な共変リターンは考慮されません。getElements()

次のようにオーバーライドします。ポリモーフィズムを失うことはありませんObject。それは、参照のタイプ (静的、コンパイル時) ではなく、 のタイプ (動的、実行時) に依存するため、依然として発生します。

public class Service extends Container
{
  public ArrayList<Container> getElements()
  {
    // declare superclass Container
    ArrayList<Container> elements = new ArrayList<Container>();

    // but add subclass ServiceMember
    elements.add(new ServiceMember());

    return elements;
  }
}
于 2013-05-20T01:41:59.907 に答える
1

Container次のようにクラスを変更するだけでよいと思います。

public class Container<T extends Container> {
   protected List<T> elements = new ArrayList<T>();

   public List<T> getElements() {
       return elements;  
   }
}

Containerこれにより、クラス (またはそれ自体)のすべてのサブクラスでパラメーター化できます。

クラスは次のServiceようになります。

public class Service extends Container<Service> {

}

最後に、これらのクラスのオブジェクトを次のようにインスタンス化できます。

Service s = new Service();
ArrayList<Service> elements = s.getElements();

Container<Container> c = new Container<Container>();
ArrayList<Container> els = c.getElements();

//adding an element to each of the lists:
c.getElements().add(new Container<Container>());
System.out.println(c.getElements().size());

s.getElements().add(new Service());
System.out.println(s.getElements().size());

とにかく、生のクラスとジェネリックを混在させることは安全ではなく、混乱を招くため、設計について非常に慎重に検討することをお勧めします。

于 2013-05-20T01:47:09.087 に答える
-1

含まれているもののタイプ Containerを示すには、と入力する必要があります。

public class Container<T extends Container<T>> {
    private List<T> elements = new ArrayList<T>();

    public List<T> getElements() {
        return elements;
    }
}

public class Service extends Container<Service> {
}

ノート:

  • タイプT extends Container<T>はそれ自体を拡張しているように見えますが、生の Container タイプを避けるように指定する方法です
  • リストは非公開です。サブクラスは getter を介して単純にアクセスする必要があります
  • グッドプラクティスに沿ってList、具体的な実装の代わりに抽象型が使用されますArrayList
于 2013-05-20T02:07:19.857 に答える