亚型中的“覆盖”实例变量:可能的风险?
-
30-09-2019 - |
题
假设我有一个从超级阶级继承的类超类和两个子类子类和子类。
abstract class SuperClass{
...
List someList;
...
}
class SubClassA extends SuperClass{
...
List<String> someList;
...
}
class SubClassB extends SuperClass{
...
List<Integer> someList;
...
}
这样它很方便,因为我可以得到 someList.size()
在 Superclass
并在子类中具有类型。问题在于它不是“感觉”,您能想到我不知道的Apporach可能的潜在危害吗?
解决方案
一方面,任何方法 SuperClass
看到超类列表,而不是子类的列表。这几乎肯定会导致细微的错误。例如,你说
我可以得到
someList.size()
在Superclass
您实际得到的是列表的大小 Superclass
, ,不是子类。超级类列表可能是空的,而子类列表包含元素(反之亦然)。
背后的原因是 SubClassA.someList
无论如何都不会取代或替代 Superclass.someList
- 它只是阴影,所以子类方法请参阅 SubClassA.someList
代替 Superclass.someList
. 。但是,这绝对没有影响 Superclass
. 。可以将方法变为虚拟(在Java中,默认情况下是),但是数据成员不能。
其他提示
这是一个非常糟糕的主意。你 真的 想要一个两个子类的实例 二 列表?因为那是正在发生的事情。您正在声明第二个变量 - 因此,超类中的代码将使用一个变量,并且子类中的代码将使用另一个变量。 IMO,这只是在要求麻烦。
我认为您应该定义方法而不是类成员变量。因此,您将能够在子类中实现方法,而不必担心类型的安全性。
我建议用方法替换变量。
谢谢。
似乎打破了IS-A和Liskov的替代原则。如果您有一系列超级类实例,每种实例都可以是子班级或子班级,那么您将充其量会得到一些令人惊讶的行为。
不要做。
也许使用仿制药会更好:
public class X<T>
{
private List<T> list;
}
不隶属于 StackOverflow