Страницы

Поиск по вопросам

вторник, 27 ноября 2018 г.

Реализовать generic для двух интерфейсов

Как реализовать generic для двух интерфейсов с возможностью затем использовать его в качестве любого из этих типов. Интересует использование этого generic для элементов List.
Код для понимания, что у меня не получается и что я хочу получить в конечном итоге:
public class Container {
private List mList;
public Container() { mList = new ArrayList(); }
public List getIFooList() { return mList; }
public List getIBarList() { return mList; }
public interface IFoo { void foo(); }
public interface IBar { void bar(); }
public static class MultiInterfacesClass implements IFoo, IBar {
@Override public void bar() {
}
@Override public void foo() {
} } }


Ответ

Можно написать
public List getIFooList() { return mList; }
List - это список элементов какого-то класса, расширяющего IFoo. Поскольку тип T extends Container.IFoo & Container.IBar расширяет IFoo, список List - подходит, и его можно вернуть.
Код:
Container container = new Container<>();
List list = container.getIFooList(); IFoo foo = list.get( 0 );
скомпилируется, но сделать
container.getIFooList().add( foo );
уже не получится. Использование типа ? extends IFoo не даст вызвать add с аргументом, отличным от null, и это хорошо, т.к. наш список на самом деле содержит объекты T extends Container.IFoo & Container.IBar, а не любых наследников IFoo
IFoo someFoo = new IFoo() { public void foo() {} }; container.getIFooList().add( someFoo );
IBar someBar = container.getIBarList().get( 0 );
Код мог бы вызвать ClassCastException во время выполнения, при присвоении someBar, но просто не скомпилируется.

Конструктор нужно переписать, как
public Container() { mList = new ArrayList(); }
либо объявить private List mList;

Комментариев нет:

Отправить комментарий