Наследование Java - конструкторы
Во время учебы в финале, я наткнулся на следующее выражение в книге, из которой я сейчас изучаю. Учитывая следующий код:
class A {
public A(int x) { }
}
class B extends A {
public B(int x ) { }
}
необходимо вызвать конструктор класса A в конструкторе класса B (super (x)). В книге говорится, что это не обязательно, потому что у них есть точное количество и тип параметров. Но когда я пробую это в компиляторе java, возникает следующая ошибка:
конструктор A в классе A не может быть применяется к данным типам; обязательный: int found: нет аргументов аргумента: списки фактических и формальных аргументов отличаются длиной
Ответы
Ответ 1
Компилятор автоматически вставляет super()
в начало.
Однако добавляются даже аргументы конструктора super()
(без аргументов), который вызывает конструктор по умолчанию суперкласса. И у вас его нет, следовательно, ошибка.
Вы должны указать super(x)
(для вызова A(x)
) или определить конструктор без аргументов.
Кстати, компилятор Eclipse дает лучшее сообщение об ошибке:
Неявный суперконструктор A() есть undefined. Необходимо явно вызвать другой конструктор
Ответ 2
Похоже, компилятор пытается создать вызов стандартного конструктора суперкласса с super()
, который недоступен:
required: int
found: no arguments
Но вернемся к вашей книге: я никогда не слышал о правиле, что вы можете пропустить оператор super
в конструкторе, если фактический конструктор имеет тот же список параметров, что и конструктор в прямом суперклассе. Только вызов конструктора по умолчанию суперкласса добавляется неявно (super()
), но для этого требуется, чтобы суперкласс имел конструктор по умолчанию.
В отличие от того, что написано в вашей книге (или в отличие от вашего понимания письменного текста), здесь предложение из спецификации языка:
Если тело конструктора не начинается с явного вызова конструктора и объявляемый конструктор не является частью первичного класса Object, тогда тело конструктора неявно предполагается компилятором, чтобы начать с супер вызов конструктора класса "super();" , вызов конструктора его прямой суперкласс, который не принимает аргументов.
Ответ 3
Если у вас есть базовый класс, имеющий конструктор по умолчанию (конструктор no-arg), когда вы расширяете B
, вам не нужно явно вызывать super()
, потому что он вызывается каким-либо образом.
Но когда у вас есть конструктор с аргументами, при создании контрмера с параметрами в B
вам нужно передать super()
параметр для A
пример:
class A {
public A(int x) { }
}
class B extends A {
public B(int x )
{
super(x); // need to specify the parameter for class A
//...
}
}
Ответ 4
Это происходит, когда у вас нет конструктора по умолчанию, и вы создаете экземпляр с по умолчанию. Потому что если у вас есть какой-либо конструктор Parameterized, тогда компилятор не будет вставлять значение по умолчанию для вас, вместо этого вы должны определить.
Ответ 5
В случае Java необходимо вызвать конструктор суперкласса. Следовательно, всякий раз, когда вы создаете конструктор подкласса, конструктор суперкласса сам создается с помощью IDE.
Это потому, что всякий раз, когда конструктор базового класса требует аргументов, компилятор считает, что они должны быть заполнены конструктором базового класса. В случае конструктора по умолчанию это нормально. Не нужно вызывать super() в подклассе.