Наследование в Java - создание объекта подкласса вызывает также конструктор суперкласса. Почему именно?

У меня вопрос о наследовании в Java.

У меня есть два класса A и B, а класс B, наследует от A:

public class A {
     public A() {
         System.out.println("Hi!");
     }
}


public class B extends A {
     public B() {
         System.out.println("Bye!");
     }

     public static void main(String[] args) {
         B b = new B();
     }
}

Когда я запускаю программу B, вывод:

Hi!
Bye!

Вопрос: почему вызывается конструктор из class A, когда я создаю и объект class B?

Я знаю, что B наследует все от A - все переменные экземпляра или класса и все методы, и в этом смысле объект B имеет все характеристики A плюс некоторые другие характеристики, определенные в B. Однако я не знал и не предполагал, что когда я создаю объект типа B, также вызывается конструктор A. Итак, пишу это:

B b = new B();

создает Два объекта - один из типов B и один из типов A.

Это становится интересным,

может кто-нибудь объяснить, почему именно это происходит?

Ответ 1

Он не создает два объекта, только один: B.

При наследовании от другого класса вы должны вызвать super() в своем конструкторе. Если вы этого не сделаете, компилятор будет вставлять этот вызов для вас, как вы можете ясно видеть.

Конструкторы суперкласса вызываются, потому что иначе объект будет оставлен в неинициализированном состоянии, возможно, без ведома разработчика этого подкласса.

Ваш подкласс действительно выглядит так, как только компилятор вставляет супервызов:

public class B extends A {
    public B() {
        super();
        System.out.println("Bye!");
    }
}

Ответ 2

Он не создает 2 объекта, он создает только один экземпляр B. Причина, вызываемая конструктором суперкласса, заключается в том, что, как вы сказали, B имеет все поля A, и эти поля должны быть инициализированы.

Ответ 3

Помните, что наследование является отношением "является" между базовым классом и подклассом, поэтому каждый раз, когда у вас есть экземпляр подкласса, по определению у вас также будет экземпляр базового класса (как часть экземпляра, а не как два отдельных экземпляра). Для правильной инициализации базового класса вызывается конструктор.

Кроме того, подумайте о том, что произойдет, если ваш подкласс зависит от некоторого внутреннего состояния базового класса. Не хотите ли вы, чтобы экземпляр базового класса был инициализирован?

Ответ 4

Это делается потому, что конструктор используется для инициализации объекта. Поскольку B также является A, он сначала вызывает конструктор для A, тогда конструктор для B.

В качестве дополнительной заметки вы можете использовать super(arg1, etc), чтобы выбрать, какой конструктор A вызывается на основе типов параметров, которые вы передаете... но это должна быть первая строка в конструкторе.

Ответ 5

Он не создает два объекта, он просто создает один объект b. b имеет тип B и типа A. Конструктор в основном говорит, что вот что вам нужно сделать, чтобы построить меня. Поэтому, когда вы создаете новый экземпляр "B", вы строите объект, который является как B(), так и A(). Представьте себе следующий сценарий:

class Q {
  int i;
  public Q() {
    // set default value
    i= 99;
  }
}

class Z extends Q {
  public Z() {
  }
}

Если конструктор для Q не был вызван, как бы получить его значение по умолчанию?

Ответ 6

Если A инициализирует члены в нем конструктором, и вы забываете называть super в производном классе, тогда члены A могут находиться в плохом состоянии. Java пытается помешать вам стрелять в ногу.

Ответ 7

Конструктор содержит всю инициализацию для A. Вы не создаете два объекта. Вы создаете один объект, а затем запускаете инициализатор для суперкласса для инициализации его членов, а затем запускаете инициализатор для класса вывода для инициализации его членов.

Ответ 8

Создан только один объект, оба подрядчика работают на одном и том же объекте.

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

например:

public class A {
     public A() {
        x = 1;
     }
     private int x;
     public int getX() {
        return x;
     }
}


public class B extends A {
     public B() {
     }

     public static void main(String[] args) {
         B b = new B();
         System.out.println(b.getX()); // should print 1 
     }
}

Ответ 9

Создание B не создает дополнительного A.

Но создав B, вы создаете вид A, потому что B является A.

Java/С++ вызывает конструктор A для вашего неявно. Зачем? Языковой дизайн. Но делать это хорошо, потому что конструктор A может содержать некоторые инициализации. И поскольку B использует все функции и ошибки A, эти функции лучше инициализируются должным образом.

Ответ 10

Конструктор класса является очень важным понятием в большинстве ООП

Классы, предоставляя состояние и средства для управления этим состоянием, позволяют легче поддерживать инварианты. Роль конструкторов заключается в том, чтобы получить класс в состояние, которое соответствует этим инвариантам (или, таким образом, запрещает использование объекта invliad). это несколько слабее, чем предполагалось на многих языках, поскольку конструктору разрешено передавать свою собственную ссылку 'this' в другом месте, но это по крайней мере находится под контролем класса (как таковой он может знать, что он находится в достаточно стабильном и действительном состоянии чтобы он был доступен для остального мира)

Наследование делает это сложным, так как B - это A в очень реальном смысле и поэтому может ссылаться на любой из методов, предоставляемых A. Части B, которые являются A, должны поэтому получить возможность инициализировать себя до того, как B будет выглядеть in, поэтому конструктор для A вызывается до начала реальной работы конструктора B.

Ответ 11

Когда создается новый объект (B), внутри B Создается объект (из-за расширений ключевых слов). В конструкторе класса B класса JVM B, но из-за расширений ключевых слов он переходит к суперклассическому конструктору. внутри Значение класса x инициализируется. Но x является частным, так что мы можем получить доступ к внешнему классу throw getXxx() и получить результат.

Ответ 12

Когда создается объект подкласса, он внутренне не создан для объекта суперкласса. Но память должна быть выделена для членов суперкласса.

Ответ 13

В java, когда вы создаете объект дочернего класса, конструктор родительского класса всегда вызывается, потому что класс Object является родителем каждого суперкласса и когда вы вызываете конструктор класса Object, тогда создается только ваш объект, а java не поддерживать множественное наследование в случае класса, поэтому, если вы расширяете любой другой класс, тогда связь между вашим дочерним классом и классом Object осуществляется через класс родителя, поэтому для вызова конструктора класса Object должен быть вызван конструктор класса Parent.

Ответ 14

если объект суперкласса не создается, то как подкласс имеет доступ к нестационарным методам и переменным суперкласса.

Я изучил, что нестатические методы и переменные доступны только через объекты.