2013-05-20 3 views
1

У меня есть Java Generics связанного вопросJava генерик с ArrayList

У меня есть класс с именем Родители Container, как показано ниже: Контейнер может содержать другие контейнеры и Services. Класс Services расширяет контейнер, но может содержать только ServiceMembers, которые также расширяют Контейнер.

Код ниже не работает, хотя в классе Services I переопределяет метод класса getElements() класса родителей и возвращает ArrayList элементов, которые также являются подклассом класса Container.

Любая идея о том, как я могу заставить это работать, или я просто использую это неправильно?

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

    public ArrayList<Container> getElements() 
    { 
    } 
} 

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

ответ

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()); 

Во всяком случае, я бы порекомендовал вам очень тщательно продумать на дизайне, потому что смешивание исходных классов с дженериками является небезопасным и запутанным.

+0

Обратите внимание, что 'Container' является сырым типом в' T extends Container'. –

+0

Привет, спасибо за ваш ответ, когда я попробую предлагаемое решение .. задавался вопросом, видели ли у вас фундаментальный недостаток в способе расположения моих объектов. Может ли посоветуете .. спасибо – Chandu

+0

также как добавить в список элементов? Я пробовал ваши предложения, и я могу вернуть тип списка, но я вижу элементы с добавлением вопросов. – Chandu

1

Ниже код не работает, даже если в классе обслуживания я переопределять getElements классовых родителей в() и возвращаю ArrayList элементов, которые также Подкласс класса Container.

Неправильное использование. Из-за тип erasureArrayList<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; 
    } 
} 
+0

Спасибо за ваш ответ. Я проверил другие объяснения в стеке и понял проблему. Но я пробовал несколько решений, а также из других сообщений, но я не очень хорошо знаком с Generic, поэтому пошел вперед и задал вопрос, может ли кто-нибудь помочь мне в правильном пути найти решение того, что я делаю .. есть лучший способ сделать это protected ArrayList elements = new ArrayList (); – Chandu

-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> кажется продлить себя, но это то, как вы определяете это так, что вы избегаете сырого контейнера типа
  • список частный: подклассы должны просто получить доступ к нему через геттер
  • абстрактный тип List используется вместо конкретной реализации ArrayList, в соответствии с хорошей практикой
+1

Можете ли вы показать нам, как бы вы создавали экземпляр класса 'Container'? –