我有两个 Java 类 B 和 C,它们都从类 A 扩展(我不拥有类 A)。
public class B extends A {…}
public class C extends A {…}
我需要一个“ListItem”类型的列表来保存 B 或 C 的实例,但由于(B 和 C)都已扩展,因此无法通过使用“ListItem”作为父类(super class)来进一步扩展它们。
我认为唯一的出路是组合(“has-a”关系……)。
因为“ListItem”永远不应该有 B 和 C(但只有其中一个),我计划用 2 个构造函数创建 ListItem 并设置一个适当的 反射(reflect) 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);
}
}
最佳答案
我的意思是,你有:
public class B extends A {…}
public class C extends A {…}
所以你可以让你的项目持有 A
:
public class ListItem {
private final A item;
public ListItem (A item) {
this.item = item;
}
}
而且你有很多关于如何从那里处理它的选项,例如简单地:
public A getItem () {
return item;
}
并从调用者那里做任何适当的转换或测试。这是最灵活的方式。或者我想是这样的:
public B getB () {
return item instanceof B ? (B)item : null;
}
public C getC () {
return item instanceof C ? (C)item : null;
}
但这开始变得草率,并限制您存储任何其他 A
衍生的东西在你的ListItem
.
您可能想在这里开始质疑您的设计。例如,如果您要向 A
添加一些功能这对 B
很常见和 C
并且是 ListItem
正常运行所必需的,考虑从 A
派生一些类要添加常见的东西,派生 B
和 C
从那开始,让你的ListItem
存储该基数(当然,如果您这样做,您将无法再存储 A
):
public class AgedA extends A {
...
public int getAge () { return ... }
}
// Then your B and C both extend AgedA, and your ListItem stores an
// AgedA and can use getAge().
你可以制作AgedA
抽象和getAge()
是虚拟的,如果那更合适的话。或者您可以声明一个定义 getAge()
的接口(interface)并使用它。
另一种选择是您可以(如评论中指出的那样)制作 ListItem
要么是一个接口(interface),要么是a class that extends A
, 然后有你的 B
和 C
实现或扩展它。
我想你也可以 use generics对于 ListItem
例如<? extends A>
,尽管这可能不合适,尤其是如果您的 ListItem
s 是混合的。使用泛型的主要好处是,例如getters 现在可以直接返回子类型而无需强制转换,并且您可以在编译时将类型限制为函数参数和内容中的特定子类型,但除此之外它与仅存储 A
基本相同。 .
无论如何,除了存储 A
的建议之外在 ListItem
并在更高级别处理不同的类型,凭良心我不能给你任何其他方法建议,因为对所有这些的需求对我来说似乎是有问题的。
关于java - 不同类型的组合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39215554/