Так что у меня возникли проблемы, обертывая вокруг себя подходящую конструкцию.Как использовать дженерики с несколькими связанными объектами?
Мое приложение имеет два ключевых объекта, которые управляют состоянием, которые должны взаимодействовать друг с другом: 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 Янг является довольно хорошим
Это похоже на меня, похоже, нет другого способа сделать это. И да, синтаксис дженериков сосет! –
Я обновил свой пример кода, чтобы включить реализацию doSomething(). –