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

Java error: Implicit super constructor is undefined for default constructor

Ошибка 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:


  1. откройте меню Проект --> Свойства или щелкните правой кнопкой мыши на вашем проекте в Проводнике пакетов и выберите Свойства (Alt + Enter в Windows, Command + I на Mac)

  2. нажмите на путь сборки Java, затем на вкладку Библиотеки

  3. выберите Путь к модулю или Путь к классу и нажмите Добавить библиотеку ... кнопка

  4. выберите системную библиотеку JRE затем нажмите Далее

  5. выберите Workspace default JRE (вы также можете выбрать другой вариант) и нажмите Готово

  6. наконец, нажмите Применить и закройте.

java inheritance