Ошибка Java: неявный суперконструктор не определен для конструктора по умолчанию
У меня есть несколько простых Java-кодов, которые по своей структуре похожи на это:
abstract public class BaseClass {
String someString;
public BaseClass(String someString) {
this.someString = someString;
}
abstract public String getName();
}
public class ACSubClass extends BaseClass {
public ASubClass(String someString) {
super(someString);
}
public String getName() {
return "name value for ASubClass";
}
}
У меня будет довольно много подклассов BaseClass
, каждый из которых реализует getName()
метод по-своему (шаблон метода шаблона).
Это работает хорошо, но мне не нравится наличие избыточного конструктора в подклассах. Его больше вводить, и его сложно поддерживать. Если бы я должен был изменить сигнатуру метода BaseClass
конструктора, мне пришлось бы изменить все подклассы.
Когда я удаляю конструктор из подклассов, я получаю эту ошибку во время компиляции:
Implicit super constructor BaseClass() is undefined for default constructor. Must define an explicit constructor
Возможно ли то, что я пытаюсь сделать?
Переведено автоматически
Ответ 1
Вы получаете эту ошибку, потому что класс, у которого нет конструктора, имеет конструктор по умолчанию, который не содержит аргументов и эквивалентен следующему коду:
public ACSubClass() {
super();
}
Однако, поскольку ваш базовый класс объявляет конструктор (и, следовательно, не имеет конструктора без аргументов по умолчанию, который в противном случае предоставил бы компилятор), это незаконно - класс, расширяющий базовый класс, не может быть вызван super();
потому что в BaseClass нет конструктора без аргументов.
Это, вероятно, немного нелогично, потому что вы можете подумать, что подкласс автоматически имеет любой конструктор, который есть у базового класса.
Самый простой способ обойти это - для базового класса не объявлять конструктор (и, следовательно, иметь конструктор без аргументов по умолчанию) или иметь объявленный конструктор без аргументов (либо сам по себе, либо вместе с любыми другими конструкторами). Но часто этот подход не может быть применен - потому что вам нужны любые аргументы, передаваемые в конструктор, чтобы создать законный экземпляр класса.
Ответ 2
Для тех, кто ищет в Google эту ошибку и попадает сюда: для ее получения может быть другая причина. Eclipse выдает эту ошибку, когда у вас есть несоответствие настройки проекта - конфигурации системы.
Например, если вы импортируете проект Java 1.7 в Eclipse и у вас неправильно настроен 1.7, вы получите эту ошибку. Затем вы можете либо перейти к Project - Preference - Java - Compiler
и switch to 1.6 or earlier
; или перейти к Window - Preferences - Java - Installed JREs
и добавить / исправить вашу установку JRE 1.7.
Ответ 3
Это возможно, но не так, как у вас есть.
Вы должны добавить конструктор без аргументов в базовый класс, и все!
public abstract class A {
private String name;
public A(){
this.name = getName();
}
public abstract String getName();
public String toString(){
return "simple class name: " + this.getClass().getSimpleName() + " name:\"" + this.name + "\"";
}
}
class B extends A {
public String getName(){
return "my name is B";
}
public static void main( String [] args ) {
System.out.println( new C() );
}
}
class C extends A {
public String getName() {
return "Zee";
}
}
Когда вы не добавляете конструктор (любой ) в класс, компилятор добавляет конструктор no arg по умолчанию для вас.
Когда defualt no arg вызывает super(); и поскольку у вас его нет в классе super, вы получаете это сообщение об ошибке.
Это касается самого вопроса.
Теперь расширяем ответ:
Вы в курсе, что создание подкласса ( поведение ) для указания другого значения (data) не имеет смысла ??!!! Я надеюсь, что вы понимаете.
Если единственное, что меняется, это "имя", то достаточно параметризовать один класс!
Так что вам это не нужно:
MyClass a = new A("A");
MyClass b = new B("B");
MyClass c = new C("C");
MyClass d = new D("D");
или
MyClass a = new A(); // internally setting "A" "B", "C" etc.
MyClass b = new B();
MyClass c = new C();
MyClass d = new D();
Когда вы сможете написать это:
MyClass a = new MyClass("A");
MyClass b = new MyClass("B");
MyClass c = new MyClass("C");
MyClass d = new MyClass("D");
Если бы я должен был изменить сигнатуру метода конструктора базового класса, мне пришлось бы изменить все подклассы.
Что ж, вот почему наследование - это артефакт, создающий ВЫСОКУЮ связь, что нежелательно в OO-системах. Его следует избегать и, возможно, заменить композицией.
Подумайте, действительно ли они вам нужны как подкласс. Вот почему вы видите, что очень часто интерфейсы используются вместо:
public interface NameAware {
public String getName();
}
class A implements NameAware ...
class B implements NameAware ...
class C ... etc.
Здесь B и C могли быть унаследованы от A, что создало бы очень ВЫСОКУЮ связь между ними, при использовании интерфейсов связь уменьшается, если A решит, что это больше не будет "NameAware", другие классы не сломаются.
Конечно, если вы хотите повторно использовать поведение, это не сработает.
Ответ 4
Вы также можете получить эту ошибку, когда JRE не установлен. Если это так, попробуйте добавить системную библиотеку JRE в свой проект.
В Eclipse IDE:
- откройте меню Проект --> Свойства или щелкните правой кнопкой мыши на вашем проекте в Проводнике пакетов и выберите Свойства (Alt + Enter в Windows, Command + I на Mac)
- нажмите на путь сборки Java, затем на вкладку Библиотеки
- выберите Путь к модулю или Путь к классу и нажмите Добавить библиотеку ... кнопка
- выберите системную библиотеку JRE затем нажмите Далее
- выберите Workspace default JRE (вы также можете выбрать другой вариант) и нажмите Готово
- наконец, нажмите Применить и закройте.