Разве конструкторы не связаны с экземплярами классов?

1

Когда super() вызывается из подкласса, он вызывается в этом "объекте", т.е. объекте, созданном оператором new Subclass(). super() вызывается на этом объекте. Но "этот" объект содержит все переменные, методы суперкласса и его самого, а также его конструкторы, но не конструктор суперкласса. Итак, как супер() вызывается на "этом" объекте?

Пожалуйста, см. Прилагаемое изображение, в котором я попытался объяснить свое понимание.

Примечание: P - суперкласс, а Q - производный класс Изображение 174551

Теги:
polymorphism
inheritance
superclass

4 ответа

5

Но "этот" объект содержит... не конструктор суперкласса.

Он "содержит" конструктор суперкласса (поскольку он "содержит" любой метод, который является немного волнистым) - просто, что единственный способ вызвать этот супер-конструктор - использовать синтаксис super(..) с его ограничениями (в частности, что он должен быть первым выражением конструктора подкласса).

Об этом размахивании руками: объект фактически не содержит метода. Методы - это статические вещи, которые вызывают в аргументах, и когда вы вызываете this.foo() он по существу переводится (с помощью JVM) в foo(this). Имя this действительно просто специальное имя для "первого аргумента метода, который всегда является тем, что я ожидаю, что this будет".

Конструкторы работают точно так же. new Foo() выделяет некоторую память, инициализирует ее переменные значениями по умолчанию (0/null) s, а затем вызывает Foo.<init>(<a reference to the new chunk of memory>). Если конструктор Foo вызывает super(), то первый оператор в Foo.<init> FooSuperClass.<init>(this) Foo.<init> по существу является FooSuperClass.<init>(this).

Это не то, как работает синтаксис Java, но это в основном то, что происходит.

Фактически, проверьте этот бит кода Java:

// in Super.java
public class Super {}

// in Sub.java
public class Sub extends Super {}

если вы выполните javap -c Sub, вы увидите:

Compiled from "Sub.java"
public class Sub extends Super {
  public Sub();
    Code:
       0: aload_0
       1: invokespecial #1        // Method Super."<init>":()V
       4: return
}

Что это делает? В 0 он выталкивает первый аргумент в конструктор Sub() (ака this) в стек, а затем в 1 вызывает Super.<init>, который выдает этот аргумент и передает его методу Super.<init>. (И, наконец, в 4 возвращается.)

3

"это" объект действительно содержит конструктор суперкласса.

Поскольку Q является дочерним классом (или производным классом) P, Q имеет доступ к тем же методам, полям и конструкторам, что и P. Конструктор super() построит экземпляр Q если речь идет о экземпляре P Любая другая инициализация должна произойти после использования super(). Обратите внимание, что super() должна быть первой строкой в конструкторе, если вы собираетесь ее использовать.

public Q()
{
    super();
    //other TO-DO...
}
  • 0
    Так Q также имеет конструктор суперкласса? Следовательно, мы можем вызвать super () напрямую, так как он из того же класса?
  • 0
    Верный! P и Q имеют доступ к одному и тому же конструктору. Рассмотрим класс Car и класс Ferrari который является подклассом Car . Возможно, вы захотите сконструировать Ferrari так же, как изначально делаете Car (следовательно, вызываете super() ), а затем установите любую другую инициализацию.
Показать ещё 2 комментария
2

В java всякий раз, когда создается подкласс, его суперкласс-конструктор называется неявным. Это связано с тем, что родительский класс должен сначала инициализировать, чтобы убедиться, что производный класс имеет все эти значения.

2

Конструктор по умолчанию (то есть один без параметров) всегда определен.

Вам не нужно предоставлять никаких конструкторов для вашего класса, но при этом вы должны быть осторожны. Компилятор автоматически предоставляет конструктор по умолчанию без аргументов для любого класса без конструкторов. Этот конструктор по умолчанию вызовет конструктор без аргументов суперкласса. В этой ситуации компилятор будет жаловаться, если суперкласс не имеет конструктора без аргументов, поэтому вы должны убедиться, что он это делает. Если у вашего класса нет явного суперкласса, то он имеет неявный суперкласс Object, у которого нет конструктора без аргументов.

См. Https://docs.oracle.com/javase/tutorial/java/javaOO/constructors.html.

Этот конструктор всегда будет неявно вызываться, но вы также можете его явно называть.

Если вы добавите конструктор P(String foo, int bar) в P, вам придется вызвать этот конструктор в Q:

public class Q {
   public Q() {
       super("answer", 42);
   }
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню