【问题标题】:How can a superclass variable hold data member values that only exist in subclass?超类变量如何保存仅存在于子类中的数据成员值?
【发布时间】:2018-08-10 18:05:19
【问题描述】:

我试图了解超类类型的变量如何将值存储在仅存在于子类中的数据成员中。

例如在 Java 中,假设类 Child 扩展了 ParentChild 有一个数据成员 childMember(假设它是一个 int)。

这在 Java 中是合法的:

Parent parentObject = new Child(); ((Child)parentObject).childMember = 5;

但是parentObject 怎么能存储childMember 的值,因为它是Parent 类型,而Parent 没有childMember?我知道它被强制转换为设置值,但它甚至如何让数据成员能够存储它,因为它不是子对象?

【问题讨论】:

  • “因为它不是子对象?” 因为它是new Child()。这与声明类型无关,而与实际实例类型有关。
  • 它是一个子对象。你写了new Child()
  • 那么即使它被声明为Parent类型,当它被分配为new Child()时它变成了Child?如果是这样,那我为什么必须将其转换为设置 childMember?
  • 没有。变量 parentObject 可以包含对 any Parent 的引用。由于Child 类扩展ParentChild 的实例也是Parents,parentObject 可以包含对其中之一的引用。任务过程中没有任何变化。但是您在分配时需要强制转换,因为原则上parentObject 也可以持有对Parent 的引用,该引用不是 Child:您断言当评估该表达式时,它实际上会引用一个Child

标签: java subclass superclass


【解决方案1】:

在这段代码中:

Parent parentObject = new Child(); 
((Child)parentObject).childMember = 5;

parentObject 对象的实际/运行时类是 Child,这就解释了为什么一切正常。

但是,由于 parentObject 是 Parent 类型而 parent 没有 childMember,它如何存储 childMember 的值?

这个问题更适用于这段代码:

Parent parentObject = new Parent(); 
((Child)parentObject).childMember = 5;

然而,在这种情况下,演员 ((Child)parentObject) 将不起作用,Java 将在运行时引发 ClassCastException,正如您所期望的那样。

【讨论】:

    【解决方案2】:

    首先,reference 的类型为 Parent它指向的对象 的类型为 Child,因此您的整个逻辑按照其他答案。

    但这是一个非常琐碎的例子,让我们做一个更有趣的例子:

    static class Parent {
        public int x = 5;
    }
    
    static class Child extends Parent {
        public int x = 3;
    }
    

    Child 有多少个x?嗯……

    Arrays.stream(Child.class.getFields())
                .map(Field::getName)
                .forEachOrdered(System.out::println); // x AND x again
    

    然后您如何访问它们中的每一个?

    Child c = new Child();
    System.out.println(c.x); // 3
    
    Parent p = c;
    System.out.println(p.x); // 5
    

    【讨论】:

    • 这是一个重要的评论......并强调了隐藏字段的危险。
    • @ernest_k 如果我们在这里(隐藏部分),那么声明静态方法final 是否有意义?
    • 我想说这没有意义。但我从来没有想过。在 IDE 中键入会导致错误(无法“覆盖”静态最终方法)
    • 也许 java 正试图保护那些使用实例(父类或子类)引用静态方法的人......这非常可悲。
    • @ernest_k 顺便说一句,你在这里触及了这么多好的主题 :) 关于你最后的评论:不 - 这一直是可能的someInstance.staticMethod(但被视为设计错误),并通过方法参考修复,你不能这样做someInstance::someStaticMethod
    猜你喜欢
    • 2021-10-04
    • 1970-01-01
    • 1970-01-01
    • 2014-06-29
    • 1970-01-01
    • 2020-04-27
    • 1970-01-01
    • 2017-08-03
    • 1970-01-01
    相关资源
    最近更新 更多