1

假设我有一个 SuperClass 类和两个从 SuperClass 继承的子类 SubClassA 和 SubClassB。

 abstract class SuperClass{
   ...
   List someList;
   ...
 }

 class SubClassA extends SuperClass{
   ...
   List<String> someList;
   ...
 }

 class SubClassB extends SuperClass{
   ...
   List<Integer> someList;
   ...
 }

这样很方便,因为我可以进入someList.size()Superclass在子类中拥有类型安全。问题是它“感觉”不对,你能想到这个方法有我不知道的潜在危险吗?

4

4 回答 4

8

一方面,任何方法都SuperClass看到超类列表,而不是子类列表。这几乎肯定会导致微妙的错误。例如,当你说

我可以someList.size()进去Superclass

您实际得到的是列表的大小Superclass,而不是子类的大小。超类列表可能为空,而子类列表包含元素(反之亦然)。

这背后的原因是它SubClassA.someList不会以任何方式替换或覆盖Superclass.someList- 它只是隐藏它,所以子类方法看到SubClassA.someList而不是Superclass.someList. 但是,这在Superclass. 方法可以是虚拟的(在 Java 中,它们是默认的),但数据成员不能。

于 2010-05-19T10:24:37.377 回答
1

对我来说似乎打破了 IS-A 和 Liskov 替换原则。如果您有一组 SuperClass 实例,每个实例都可以是 SubClassA 或 SubClassB,那么您最多会得到一些令人惊讶的行为。

不要这样做。

也许使用泛型的东西会更好:

public class X<T>
{
    private List<T> list;
}
于 2010-05-19T11:21:18.857 回答
1

我认为您应该定义一个方法而不是类成员变量。这样您就可以在子类中实现方法,而不必担心类型安全。

用我建议的方法替换变量。

谢谢。

于 2010-05-19T11:24:52.123 回答
1

这是一个非常糟糕的主意。您真的希望任一子类的实例都有两个列表吗?因为这就是正在发生的事情。您正在声明第二个变量 - 因此超类中的代码将使用一个变量,而子类中的代码将使用另一个。这只是自找麻烦,IMO。

于 2010-05-19T10:27:15.350 回答