Вопрос-ответ

Java Constructor Inheritance

Наследование конструктора Java

Мне было интересно, почему в Java конструкторы не наследуются? Вы знаете, когда у вас есть такой класс, как этот:

public class Super {

public Super(ServiceA serviceA, ServiceB serviceB, ServiceC serviceC){
this.serviceA = serviceA;
//etc
}

}

Позже, когда вы будете наследовать от Super, java будет жаловаться, что конструктор по умолчанию не определен. Решение, очевидно, что-то вроде:

public class Son extends Super{

public Son(ServiceA serviceA, ServiceB serviceB, ServiceC serviceC){
super(serviceA,serviceB,serviceC);
}

}

Этот код повторяющийся, а не СУХОЙ и бесполезный (ИМХО)... в связи с этим снова возникает вопрос:

Почему java не поддерживает наследование конструкторов? Есть ли какая-либо выгода в том, чтобы не разрешать это наследование?

Переведено автоматически
Ответ 1

Предположим, что конструкторы были унаследованы ... тогда, поскольку каждый класс в конечном итоге является производным от Object, каждый класс в конечном итоге получит конструктор без параметров. Это плохая идея. Чего именно вы ожидали бы:

FileInputStream stream = new FileInputStream();

что делать?

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

Ответ 2

Когда вы наследуете от Super, это то, что происходит на самом деле:

public class Son extends Super{

// If you dont declare a constructor of any type, adefault one will appear.
public Son(){
// If you dont call any other constructor in the first line a call to super() will be placed instead.
super();
}

}

Итак, в этом причина, потому что вы должны вызвать свой уникальный конструктор, поскольку у "Super" нет конструктора по умолчанию.

Теперь попытаемся угадать, почему Java не поддерживает наследование конструктора, вероятно, потому, что конструктор имеет смысл, только если речь идет о конкретных экземплярах, и вы не сможете создать экземпляр чего-либо, если не знаете, как это определено (с помощью полиморфизма).

Ответ 3

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

Глупый пример:

class Super {
protected final Number value;
public Super(Number value){
this.value = value;
}
}

class Sub {
public Sub(){ super(Integer.valueOf(0)); }
void doSomeStuff(){
// We know this.value is an Integer, so it's safe to cast.
doSomethingWithAnInteger((Integer)this.value);
}
}

// Client code:
Sub s = new Sub(Long.valueOf(666L)): // Devilish invocation of Super constructor!
s.doSomeStuff(); // throws ClassCastException

Или еще проще:

class Super {
private final String msg;
Super(String msg){
if (msg == null) throw new NullPointerException();
this.msg = msg;
}
}
class Sub {
private final String detail;
Sub(String msg, String detail){
super(msg);
if (detail == null) throw new NullPointerException();
this.detail = detail;
}
void print(){
// detail is never null, so this method won't fail
System.out.println(detail.concat(": ").concat(msg));
}
}
// Client code:
Sub s = new Sub("message"); // Calling Super constructor - detail is never initialized!
s.print(); // throws NullPointerException

Из этого примера вы видите, что вам понадобится какой-то способ объявить, что "Я хочу наследовать эти конструкторы" или "Я хочу наследовать все конструкторы, кроме этих", а затем вам также нужно будет указать предпочтение наследования конструктора по умолчанию на случай, если кто-то добавит новый конструктор в суперкласс... или вы могли бы просто потребовать, чтобы вы повторяли конструкторы из суперкласса, если вы хотите их "наследовать", что, возможно, является более очевидным способом сделать это.

Ответ 4

Поскольку конструкторы являются деталью реализации, пользователь интерфейса / суперкласса вообще не может их фактически вызывать. К моменту получения экземпляра он уже сконструирован; и наоборот, на момент создания объекта по определению нет переменной, которой он в данный момент присвоен.

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

java inheritance