【问题标题】:Are objects of parent classes implicitly created when instantiating an object of a child class实例化子类的对象时是否隐式创建父类的对象
【发布时间】:2019-09-30 14:55:59
【问题描述】:

我对这个代码示例感到困惑:

我很困惑为什么要先调用 draw 的子方法。我很困惑,因为当在 main 中实例化 RoundGlyph 时,超级构造函数不是在子对象之前实例化父对象吗?

class Glyph {
    void draw() {
        System.out.println("test"); // method will be called once you create a Glyph object, because when we create a round glyph before creating a glyph the super constructor will be called
    }

    void print2() {
        System.out.println("printed from print 2");
    }

    int y1;

    Glyph() {
        y1 = 5;
        System.out.println("y1 = " + y1);
        System.out.println("Glyph() before draw()");
        draw();
        System.out.println("Glyph() after draw()");
        print2();
    }
}

class RoundGlyph extends Glyph {
    int radius = 1;

    RoundGlyph(int r) {
        System.out.println("radius in RoundGlyph=" + radius);
        radius = r;
        System.out.println("RoundGlyph.RoundGlyph(), radius = "+ radius);
    }

    void draw() {
        System.out.println("RoundGlyph.draw(), radius = " + radius);
    }
}

public class PolyConstructors {
    public static void main(String[] args) {
        new RoundGlyph(5);
        //new Glyph();
    }
}

【问题讨论】:

  • 因为它是在 RoundGlyph 的一个实例上调用的
  • 构造函数是隐式调用的。 draw() 方法在孩子中被覆盖,因此它将被调用而不是父方法。
  • 如果要执行父级的代码,可以使用super();
  • 这就是为什么你应该从不在构造函数中调用一个可覆盖的方法。

标签: java inheritance


【解决方案1】:

1 - 当你创建一个子类对象时,子类构造函数 叫做。子类构造函数调用父类构造函数。

2 - 为什么调用父类构造函数?

你必须知道子类具有父类的所有属性 班级。所以当你创建一个子类对象时,所有的属性 父类的在子类中可用,除了私有。

3 - 构造函数调用做什么?

构造函数调用为其所有变量分配默认值,但这样做 不创建父类的对象。

4 - 我们如何证明没有创建父类的对象?

如你所知,我们可以继承抽象类。当孩子 类是对象被创建它也调用抽象类构造函数。

我们知道我们不能创建抽象类的对象。

【讨论】:

    【解决方案2】:

    在构造函数RoundGlyph(int r)作为第一行,在System.out.println之前java会隐式调用超类Glyph()的构造函数supper()see this post

    【讨论】:

      【解决方案3】:

      创建整个对象(即子结构和父结构),然后按父子顺序调用构造函数。

      如果父类的构造函数调用在子类中被覆盖的方法,则调用子类的方法(遵循覆盖语义);在构造函数中没有什么特别之处。

      请注意,在构造函数中调用非 final 方法是一个非常糟糕的主意(这是 Joshua Bloch 的“Effective Java”中的一项),正是出于这个原因:孩子覆盖它的方法可能会访问尚未初始化的子字段。

      例如

      class Parent {
          Parent() {
              method();
          }
          void method() { System.out.println(); }
      }
      
      class Child extends Parent {
          String output = "hello";
          void method() { if (output.equals("hello")) System.out.println(output); }
      }
      

      Parent 的构造函数将在 output 初始化之前被调用(由于超类优先初始化),因此覆盖 method 将遇到 NullPointerException

      【讨论】:

        猜你喜欢
        • 2021-11-17
        • 2015-04-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多