2015-09-13 4 views
3

Так что у меня возникли проблемы, обертывая вокруг себя подходящую конструкцию.Как использовать дженерики с несколькими связанными объектами?

Мое приложение имеет два ключевых объекта, которые управляют состоянием, которые должны взаимодействовать друг с другом: ItemList, ItemState. Каждый из них полагается на общий ITEM_TYPE, чтобы они могли функционировать в разных контекстах. Они также абстрактны, чтобы допускать поведение, зависящее от ITEM_TYPE.

Обе части должны знать общий тип, но более того, поскольку они разговаривают друг с другом, им необходимо знать общие типы друг друга. (ItemList < String> instance должен знать, что его поле ItemState - ItemState < String> и наоборот).

Мое текущее решение работает, но оно кажется ужасным. Там должен быть лучший путь. Это то, что я делаю сейчас:

public abstract class ItemState< 
    ITEM_TYPE, 
    STATE_TYPE extends ItemState<ITEM_TYPE, STATE_TYPE, LIST_TYPE>, 
    LIST_TYPE extends ItemList<ITEM_TYPE, STATE_TYPE, LIST_TYPE>> { 

} 
public abstract class ItemList< 
    ITEM_TYPE, 
    STATE_TYPE extends ItemState<ITEM_TYPE, STATE_TYPE, LIST_TYPE>, 
    LIST_TYPE extends ItemList<ITEM_TYPE, STATE_TYPE, LIST_TYPE>> { 

} 

Тогда класс реализации может выглядеть следующим образом:

class StringState extends ItemState<String, StringState, StringList> { 

} 
class StringList extends ItemList<String, StringState, StringList> { 

} 

Обратите внимание, что для ItemState, STATE_TYPE является ссылкой обратно реализующего класса, также и для ITEMLIST/LIST_TYPE.

На самом деле моя проблема будет решена, если я просто сделаю ItemState внутренним классом ItemList, так как будет неявное связывание, и они могут делиться общими объявлениями, но оба класса настолько велики и автономны, что я бы предпочел не делать это.

Любые предложения?

Edit: Как контрпример на комментарий:

public abstract class ItemState<ITEM_TYPE> { 
    public abstract ItemList getItemList(); 
    public void doSomething() { 
    // This should not compile because abstract super class has 
    // no idea what the generic type of getItemList() is 
    ITEM_TYPE item = this.getItemList.getItem(); 
    } 
} 

Edit 2: Я думаю, что лучшее решение, которое я мог думать только, чтобы сделать ITEMLIST/ItemState наследуют одну или другую, таким образом они может функционировать как один и тот же класс. Я не люблю это решение, потому что оно отменяет разделение проблем, но это делает дженерики более управляемыми.

Sidenote: моя фактическая аппликация имела эту проблему с 4 переплетенными классами, я просто использовал 2 для простоты. В действительности дженерики были настолько плохими, что они были непонятными и сложными для рефакторинга (около 4 целых строк только общих объявлений для каждого класса). Я теперь сделал эти 4 класса в вертикальную иерархию наследования решение

JM Янг является довольно хорошим

+0

Это похоже на меня, похоже, нет другого способа сделать это. И да, синтаксис дженериков сосет! –

+0

Я обновил свой пример кода, чтобы включить реализацию doSomething(). –

ответ

1

Я думаю, вы можете просто ссылаться на общий тип item_type при объявлении этих 2 классов.

Я могу скомпилировать под кодом без ошибок.

public abstract class ItemList<ITEM_TYPE> { 
    public abstract ItemState<ITEM_TYPE> getState(); 

    public abstract ITEM_TYPE getItem(); 
} 

public abstract class ItemState<ITEM_TYPE> { 
    public abstract ItemList<ITEM_TYPE> getItemList(); 

    public void doSomething() { 
     ITEM_TYPE item = getItemList().getItem(); 
     System.out.println(item); 
    } 
} 

public class StringList extends ItemList<String> { 
    @Override 
    public StringState getState() { 
     return new StringState(); 
    } 

    @Override 
    public String getItem() { 
     return ""; 
    } 
} 

public class StringState extends ItemState<String> { 
    @Override 
    public StringList getItemList() { 
     return new StringList(); 
    } 
} 
+0

Проблема заключается в том, что при работе в абстрактном базовом классе невозможно определить, имеет ли связанный объект тот же тип. – sicklybeans

+0

Не могли бы вы продумать пример? –

+0

Как вы можете видеть в моем коде, в абстрактном классе ItemList , вы используете ItemState , чтобы связанный объект имел тот же тип, в абстрактном классе ItemState , вы используете ItemList для этой же цели. –

Смежные вопросы