不同类型的java组合
我有两个Java类B和C,它们都是从类A扩展而来的(我不拥有类A)
public class B extends A {…}
public class C extends A {…}
我需要一个“ListItem”类型的列表来保存B或C的实例,但由于(B和C)都已扩展,因此不能通过使用“ListItem”作为超类来进一步扩展它们
我认为唯一的方法是组合(“has-a”关系…)
由于“ListItem”不应该有B和C(但只能有一个),我计划用两个构造函数创建ListItem,并设置一个适当的 内部类型,以反映B或C是否处于保留状态
有没有更好的方法来实现这一点?请参阅下面的伪代码
public class ListItem {
private enum elemType {
TYPE_B, TYPE_C
}
private final B mBItem;
private final C mCItem;
private final elemType mType;
// used to hold instance of B
public ListItem(B b) {
this.mBItem = b;
this.mType = TYPE_B;
}
// used to hold instance of C
public ListItem(C c) {
this.mCItem = c;
this.mType = TYPE_C;
}
// sample method to demonstrate delegation
private int getAge() {
int age;
if (containsB()) {
age = mBItem.getAge();
}
else if (containsC()) {
age = mCItem.getAge();
}
else {…}
return age;
}
private boolean containsB() {
return (mType == TYPE_B);
}
private boolean containsC() {
return (mType == TYPE_C);
}
}
# 1 楼答案
我认为一个干净的方法是让
ListItem
成为从A
扩展而来的抽象类,然后让B
和C
从ListItem
扩展而来为什么要把
ListItem
抽象化?跨B
和C
共享的任何行为都可以在抽象类中实现,您还可以对其子类施加接口要求然后,您可以声明
ListItem
的列表,根据需要插入B
和C
的实例,并根据ListItem
中的具体方法或抽象接口操作它们:# 2 楼答案
从您的描述来看,
ListItem
似乎是a型项目(B或C,未来的其他子类)的容器。我建议使用泛型,使用<? extends A>
,这样就不需要多个构造函数,A的所有方法都应该可用# 3 楼答案
我是说,你有:
所以你可以把你的物品放在
A
上:你可以从那里选择如何处理它,例如:
并对调用者进行适当的强制转换或测试。这是最灵活的方式。或者我想是这样的:
但这已经开始变得草率,并且限制了您在
ListItem
中存储任何其他A
派生的内容你可能想在这里开始质疑你的设计。例如,如果将^ {CD1}}添加到^ {CD5> }和^ {CD6> } EM的某些功能,并且对于{{CD3}} EEM的正确操作是必要的,考虑从^ {< CD1> }导出某个类,以添加普通的东西,从中导出^ {CD5}}和^ {CD6}},然后让你的
ListItem
存储这个基础(当然,如果你这样做,你就不能再存储A
):如果更合适的话,你可以把
AgedA
抽象化,把getAge()
虚拟化。或者您可以声明一个定义getAge()
的接口并使用它还有一个选择是(正如评论中指出的那样)让} ,然后让
ListItem
成为一个接口,或者a class that extends ^{B
和C
实现或扩展它我想你也可以use generics表示
ListItem
,例如<? extends A>
,尽管这可能不合适,尤其是当你的ListItem
是混合的时候。使用泛型的主要好处是,例如,getter现在可以直接返回子类型,而无需强制转换,并且您可以在编译时将类型限制为函数参数和内容中的特定子类型,但除此之外,它本质上与存储A
是一样的在任何情况下,除了建议将
A
存储在ListItem
中并在更高级别上处理不同的类型之外,我不能凭良心向您提供任何其他方法建议,因为对所有这些的需求在我看来都是可疑的