【问题标题】:super() constructor within a subclass that extends a subclass?扩展子类的子类中的 super() 构造函数?
【发布时间】:2013-05-02 03:41:22
【问题描述】:

我不确定我的问题措辞是否正确,但我对这些代码行感到困惑。

public class First {
    public String name() {
        return "First";
    }
}

public class Second extends First {
    public void whoRules() {
        System.out.print(super.name() + " rules");
        System.out.println(" but " + name() + " is even better");
    }
    public String name() {
        return "Second";
    }
}

public class Third extends Second {
    public String name() {
        return "Third";
    }
}

Second varSecond = new Second();
Third varThird = new Third();
varSecond.whoRules();
varThird.whoRules();

当上面执行时,它会打印出来

First rules but second is even better

First rules but third is even better

为什么不呢:

First rules but second is even better

Second rules but third is even better

一个子类可以成为另一个类的超类吗?还是只能有一个(超类)? (使用上面的示例代码) 我知道FirstSecond 的超类,但SecondThird 的超类吗? 还是FirstThird 的超类?

如果有 10 个类相互扩展(第二个扩展第一个,第三个扩展第二个,等等)所有这些类的超类是否都是 First?)

【问题讨论】:

  • super.name() 存在于第二个类中,尽管方法 whoRules() 被继承,但其中的 super.name() 仍然指向 Second 的超类的名称,在您的情况下是 @ 987654335@

标签: java inheritance constructor overriding


【解决方案1】:

为什么不这样:……“第二个规则,但第三个更好”

因为 Second 类中的 super.name() 指的是 Second 的超类,而不是实例的超类。

来自Java Language Specificationsuper.Identifier 形式引用当前对象的名为 Identifier 的字段,但当前对象被视为当前类的超类的一个实例。

一个子类可以成为另一个类的超类吗?

是的。

或者只能有一个(超类)?

每个类最多可以有一个直接超类,而后者又可以有它的超类,等等。

(使用上面的示例代码)我知道 First 是 Second 的超类,但 Second 是 Third 的超类吗?还是 First 是 Third 的超类?

First 和 Second 都是 Third 的超类。

Second 是 Third 的 direct 超类。

【讨论】:

  • 何时/如何引用 Second?
  • 关键字“super”仅在 Second 的直接子类中引用类 Second。如果你想要对象类的超类,你可以通过 this.getClass() 返回的 Class 对象来实现。
【解决方案2】:
Third varThird = new Third();

因为第三类没有 whoRules() 方法。它调用超类方法。

如果调用过程中没有指定对象,编译器使用“this”关键字调用。所以这就是为什么,this.name() 打印“第三”作为 whoRules() 方法被第三个 Class 对象调用。因此结果 - “第一个规则,但第三个更好。”

【讨论】:

    【解决方案3】:

    这是因为你从第二类调用 super ,它从第一类调用 super.name() 。 第二个的上级总是第一个

    【讨论】:

      【解决方案4】:

      这是简单的继承。 First 是 Second 的超类, Second 是 Third 的超类。基本上,当您创建类 Third 的对象时,它将继承父类的所有(非私有)属性,即 First 类和 Second 类。

      First -> Second -> Third 
      

      Super 关键字 - 在给定的示例中,您将在子类中覆盖(在子类中实现超类方法)超类 First 的方法 name()。使用关键字 super。 name() 让您可以调用超类的 name() 方法。

      我希望你记住的最重要的事情是

      java编译器调用一个基于Reference类型的方法而不是 对象类型

      当你说

      varSecond.whoRules();
      

      在这种情况下,对象引用属于第二类

      System.out.print(super.name() + " rules");//calls the name() in class First
      System.out.println("but" + name()+"is even better");//calls the name() in class Second
      

      但是当你说

      varThird.whoRules();
      

      在这种情况下,对象引用属于类 Third

      System.out.print(super.name() + " rules");//calls the name() in class First
      System.out.println("but" + name()+"is even better");//calls the name() in class Third
      

      仅仅是因为 name() 方法是在类 Third 中定义的。如果你没有在类 Third 中定义 name() 方法,它会调用超类方法。

      并回答您的其他问题,继承深度没有硬性限制,但通常您不会在良好设计的层次结构中看到 10 个超类。

      【讨论】:

      • 这完全是错误的:“Java 编译器根据引用类型而不是对象类型调用方法”
      • @AndyThomas-Cramer 你能解释一下这是怎么回事吗?
      • 动态方法调用是基于运行时的对象类型,而不是编译时的引用类型。这是面向对象开发的基石之一。
      • @andythomas-Cramer 我在 java 方面不是很有经验,我首先提到了 Head,他们至少说了 5 次同样的话。
      • 那本书说编译器使用引用类型来查看你是否可以调用该方法。在运行时调用的 actual 方法基于对象类型。见oreilly.com/catalog/hfjava2/chapter/ch08.pdf
      猜你喜欢
      • 2017-09-04
      • 1970-01-01
      • 2014-02-17
      • 1970-01-01
      • 2013-06-05
      • 1970-01-01
      • 1970-01-01
      • 2014-09-13
      • 1970-01-01
      相关资源
      最近更新 更多