【问题标题】:Safety of subclass data when returned as superclass作为超类返回时子类数据的安全性
【发布时间】:2013-07-25 16:00:05
【问题描述】:

当您在 Java 中的超类类型的方法中返回子类时,我很难找到具体情况。例如:

    public class SuperClass
    {
        int a;
    }
    public class SubClass extends SuperClass
    {
        int b;
    }


    SuperClass superObj;
    SubClass subObj;

    private SuperClass getObject ()
    {
        return subObj;
    }


    public static void main (...)
    {
        superObj = getObject();
    }

当 subObj 作为其超类返回时,它究竟会发生什么?我在输入这个例子时意识到,我自己也可以很容易地测试它,但我仍然很好奇发生这种情况时的具体过程是什么,以及它是否被认为是好的(如果它有效的话)还是不好的做法.

我之所以问,是因为我目前正在从事一个项目,其中我有两个抽象基类,每个基类都有几个子类。我试图找出处理必须从一个子类更改为另一个子类的好/坏方法,同时仍然使用使用抽象基类时添加的便利多态性。

编辑:我修复了 main 和 class 声明,对此感到抱歉。

【问题讨论】:

    标签: java polymorphism return-type


    【解决方案1】:

    转换不会从根本上将对象更改为不同的类型,它只是告诉编译器将对象视为其超类(或向下转换时的子类)。在您的示例中,superObj 仍然是 SubClass 类型的实例,但它现在 似乎 是一个 SuperClass。这意味着如果你尝试引用superObj.b,你会得到一个编译错误(因为超类中不存在b)。但是您可以参考(SubClass)superObj.b。在这种情况下,您是在告诉编译器将 subClass 视为 SubClass 的一个实例(确实如此)。

    让我们更进一步,在您的代码中添加另一个类:

    public class SisterClass extends SuperClass
    {
        int c;
    }
    

    不更改代码中的任何其他内容(语法问题除外),您尝试引用((SisterClass)superObj)。这将编译但因 ClassCastRuntime 运行时错误而失败。虽然 SisterClass 是 SuperClass 的子类,但 superObj 不是 SisterClass 的instance。因此,您只能转换为对象实际上是

    【讨论】:

      【解决方案2】:

      您的代码中有一些奇怪的地方(在 main 中定义一个方法?),但不能忍受... getObject 方法不会更改您的 subObj,它只会返回一个看起来像 SuperClass 类型的引用。 “看起来”是指它只会公开 SuperClass 中的任何方法或成员。但是,如果您采用该返回值并尝试将其向下转换为 SubClass,则转换将成功,您会发现 SubClass 中的字段/方法将按您预期的方式工作,而不会因作为 SuperClass 返回而丢失任何信息。

      【讨论】:

        【解决方案3】:

        子类是超类的扩展

        您只是将其转换为它的基类,所有扩展都不可用,您不应该尝试将它们恢复到实现,因为您会猜测它们是什么,因为您可以在各种方式,

        返回的类有 a 但没有 b

        【讨论】:

        • 值得注意的是,如果你引用了 SuperClass 类型的对象,那么 Java 将允许你查询它以确定它是否是更具体的类型(在本例中为子类)和会让你在适当的时候感到沮丧。
        • @tuckermi 如果您一开始就返回 Basetype,则表明设计不佳。
        • 虽然这通常是正确的,但在某些情况下,向下转换是可以接受的。而且,更重要的是,我认为值得一提,因为它突出了 JVM 正在做的事情,与其他语言/运行时如何处理向上转换相比。
        猜你喜欢
        • 2018-12-28
        • 2017-04-06
        • 1970-01-01
        • 2013-10-17
        • 1970-01-01
        • 2015-03-09
        • 2013-01-02
        • 2020-11-14
        • 1970-01-01
        相关资源
        最近更新 更多