因此,我无法为正确的设计缠住头。
我的应用程序有两个控制状态的关键对象,它们需要彼此交互:ItemList,ItemState。它们每个都依赖于通用的ITEM_TYPE,因此它们可以在不同的上下文中运行。它们也是抽象的,以允许依赖于ITEM_TYPE的行为。
这两部分都需要知道通用类型,而且,由于它们彼此交谈,因此他们需要知道彼此的通用类型。 (ItemList 实例需要知道其ItemState字段是ItemState ,反之亦然)。
我当前的解决方案有效,但是似乎很糟糕。一定有更好的方法。这就是我现在正在做的:
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的内部类,确实会解决我的问题,因为将存在隐式绑定并且它们可以共享通用声明,但是两个类都非常大且独立,因此我不希望这样做。
有什么建议?
编辑:作为评论的反例:
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();
}
}
编辑2:我认为我能想到的最好的解决方案是使ItemList / ItemState继承一种或多种方式,以便它们可以充当同一类。我不喜欢这种解决方案,因为它覆盖了关注点分离,但是它使泛型更易于管理。
旁注:我的实际应用程序在4个交错的类中遇到了这个问题,为简单起见,我只使用了2个。实际上,泛型是如此糟糕,以至于难以理解且难以重构(每个类仅约4行,仅泛型声明)。我现在已经将这4个类做成一个垂直继承层次结构
杨俊杰的解决方案很好
最佳答案
我认为您在声明这两个类时可能只引用通用类型ITEM_TYPE。
我能够编译以下代码而不会出错。
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();
}
}