“压倒一切”子类型中的实例变量:可能的风险?

发布于 2024-09-02 06:00:38 字数 459 浏览 4 评论 0原文

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

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

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

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

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

Say I had a class SuperClass and two subclasses SubClassA and SubClassB that inherit from SuperClass.

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

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

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

That way it is convenient because I can get someList.size() in Superclass and have Typesafety in the Subclasses.
The problem is that it does not "feel" right, can you think of potential hazards this apporach has that I am not aware of?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

原野 2024-09-09 06:00:38

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

我可以在Superclass中获取someList.size()

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

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

For one thing, any method of SuperClass sees the superclass list, not that of the subclass. This almost surely leads to subtle bugs. E.g. when you say

I can get someList.size() in Superclass

what you actually get is the size of the list in Superclass, not that of the subclass. The superclass list may be empty while the subclass list contains elements (or vice versa).

The reason behind this is that SubClassA.someList does not in any way replace or override Superclass.someList - it just shadows it, so the subclass methods see SubClassA.someList instead of Superclass.someList. However, this has absolutely no effect in Superclass. Methods can be made virtual (and in Java, they are by default), but data members can't.

千紇 2024-09-09 06:00:38

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

This is a really bad idea. Do you really want an instance of either subclass to have two lists? Because that's what is happening. You're declaring a second variable - so code in the superclass will use one variable, and code in the subclass will use another. That's just asking for trouble, IMO.

握住我的手 2024-09-09 06:00:38

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

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

谢谢。

I think you should rather define a method instead of the class member variable. So that you will be able to implement methods in your sub classes and don't need to worry about the type safety.

Replace variable with Method i suggest.

thanks.

野生奥特曼 2024-09-09 06:00:38

对我来说似乎违反了 IS-A 和里氏替换原则。如果您有一组 SuperClass 实例,其中每个实例都可以是 SubClassA 或 SubClassB,那么您充其量只会得到一些令人惊讶的行为。

不要这样做。

也许使用泛型会更好:

public class X<T>
{
    private List<T> list;
}

Seems to break IS-A and the Liskov Substitution Principle to me. If you have a collection of SuperClass instances, each of which can be SubClassA or SubClassB, you'll get some surprising behavior at best.

Don't do it.

Maybe something using generics would be better:

public class X<T>
{
    private List<T> list;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文