难以掌握继承权 [英] Trouble trying to grasp inheritance

查看:116
本文介绍了难以掌握继承权的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给定Main.java:

Given Main.java:

public class Main{
    public static void main(String[]args){
          A a = new B();
          a.print();
    }

}

class A{
       A() {print();}
       void print() { System.out.println("A"); }
}

class B extends A{
       int i = 4;
       void print() { System.out.println(i); }
}

结果:

0

4.
但是如果a.print引用A类,为什么不输出A?在这样的情况下,我如何知道一种方法何时会被调用?为什么A的构造函数被调用并且仍在使用B的方法?

Results in:
0
4.
But why doesn't a.print output "A" if it is referencing Class A? How do I know when one method will called be over another in cases like this? Why is A's constructor being called and still using B's method?

推荐答案

调用 a.print()由于 4 >多态性。调用的方法取决于 a 的运行时类型,即 B 。什么时候被召唤并不重要;多态性始终适用。

Calling a.print() prints 4 because of polymorphism. The method called depends on the runtime type of a, which is B. It doesn't matter when it's called; polymorphism applies always.

两次, B 打印调用方法。一次来自 A 的构造函数,由 B 中的默认构造函数调用。另一次是您在 main 中的显式调用。

Both times, B's print method is called. Once is from A's constructor, which is called by the default constructor in B. The other time is your explicit call in main.

第一次打印产生的原因 0 而不是 4 是因为在调用 print 时, A 仍在构建中。也就是说, A 构造函数仍在执行中。在超类构造函数返回之前,尚未在子类中初始化任何内容,甚至不是变量初始值设定项。在超类构造函数完成之后,但在子类构造函数的其余部分完成之前,将分配值 4 。因为变量初始值设定项尚未运行,所以 0 的默认值(对于<$ c,它将是 false $ c> boolean s和 null for objects)是 i 中的值第一次打印。

The reason that the first printing yields 0 and not 4 is because at the time that print is called, A is still being constructed. That is, the A constructor is still being executed. Before a superclass constructor returns, nothing is initialized in the subclass yet, not even variable initializers. The value 4 is assigned after the superclass constructor completes, but before the rest of the subclass constructor completes. Because the variable initializers haven't run yet, the default value of 0 (it would be false for booleans and null for objects) is the value of i in the first printing.

此订单由 JLS,第12.5节


在引用新创建的对象之前返回结果,处理指示的构造函数以使用以下过程初始化新对象:

Just before a reference to the newly created object is returned as the result, the indicated constructor is processed to initialize the new object using the following procedure:


  1. 分配参数用于此构造函数调用的新创建的参数变量的构造函数。

  1. Assign the arguments for the constructor to newly created parameter variables for this constructor invocation.

如果此构造函数以另一个构造函数的显式构造函数调用(第8.8.7.1节)开头相同的类(使用此),然后使用这些来递归地计算参数和处理构造函数调用同样的五个步骤。如果该构造函数调用突然完成,则此过程突然完成,原因相同;否则,继续执行步骤5.

If this constructor begins with an explicit constructor invocation (§8.8.7.1) of another constructor in the same class (using this), then evaluate the arguments and process that constructor invocation recursively using these same five steps. If that constructor invocation completes abruptly, then this procedure completes abruptly for the same reason; otherwise, continue with step 5.

此构造函数不以同一类中另一个构造函数的显式构造函数调用开始(使用此方法)。如果此构造函数用于Object以外的类,则此构造函数将以超类构造函数的显式或隐式调用开始(使用super)。使用这五个相同的步骤评估参数并递归处理超类构造函数调用。如果该构造函数调用突然完成,则由于同样的原因,此过程突然完成。否则,继续执行步骤4.

This constructor does not begin with an explicit constructor invocation of another constructor in the same class (using this). If this constructor is for a class other than Object, then this constructor will begin with an explicit or implicit invocation of a superclass constructor (using super). Evaluate the arguments and process that superclass constructor invocation recursively using these same five steps. If that constructor invocation completes abruptly, then this procedure completes abruptly for the same reason. Otherwise, continue with step 4.

为此类执行实例初始化程序和实例变量初始化程序,分配实例变量的值对应实例变量的初始值设定项,按从左到右的顺序,它们以文本方式出现在类的源代码中。如果执行任何这些初始值设定项导致异常,则不会处理其他初始值设定项,并且此过程会突然完成同样的异常。否则,继续执行步骤5.

Execute the instance initializers and instance variable initializers for this class, assigning the values of instance variable initializers to the corresponding instance variables, in the left-to-right order in which they appear textually in the source code for the class. If execution of any of these initializers results in an exception, then no further initializers are processed and this procedure completes abruptly with that same exception. Otherwise, continue with step 5.

执行此构造函数的其余部分。如果该执行突然完成,则由于同样的原因,此过程突然完成。否则,此程序正常完成。

Execute the rest of the body of this constructor. If that execution completes abruptly, then this procedure completes abruptly for the same reason. Otherwise, this procedure completes normally.


(大胆强调我的)

这是为什么调用可以从构造函数重写的方法的一个坏主意的示例。子类状态尚未初始化。

This is an example of why it's a bad idea to call a method that can be overridden from a constructor. The subclass state isn't initialized yet.

这篇关于难以掌握继承权的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆