Ошибка Java: неявный супер-конструктор undefined для конструктора по умолчанию

У меня есть простой 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();
}

Однако, поскольку ваш BaseClass объявляет конструктор (и, следовательно, не имеет конструктора no-arg по умолчанию, который в противном случае предоставил компилятор), это незаконно - класс, который расширяет BaseClass, не может вызвать super();, потому что есть не конструктор без аргументов в BaseClass.

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

Самый простой способ заключается в том, что базовый класс не объявляет конструктор (и, следовательно, имеет конструктор по умолчанию, no-arg) или имеет объявленный конструктор no-arg (сам по себе или рядом с любыми другими конструкторами). Но часто этот подход не может быть применен - ​​потому что вам нужны все аргументы, которые передаются в конструктор для создания законного экземпляра класса.

Ответ 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

Возможно, но не так, как у вас есть.

Вам нужно добавить конструктор no-args в базовый класс и что он!

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";
    }
}

Если вы не добавляете конструктор (any) в класс, компилятор добавляет для вас конструктор по умолчанию no arg.

Когда defualt no arg вызывает super(); и поскольку у вас его нет в суперклассе, вы получите это сообщение об ошибке.

Что касается вопроса, то это сам.

Теперь, расширяя ответ:

Знаете ли вы, что создание подкласса (поведения) для указания другого значения (данных) не имеет смысла?!!! Надеюсь, вы это сделаете.

Если единственное, что есть изменения, это "имя", то достаточно одного параметризованного класса!

Поэтому вам это не нужно:

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");

Если бы мне пришлось изменить сигнатуру метода конструктора BaseClass, мне пришлось бы изменить все подклассы.

Хорошо, что наследование - это артефакт, который создает HIGH-сцепление, что нежелательно в OO-системах. Его следует избегать и, возможно, заменить композицией.

Подумайте, действительно ли они действительно нужны в качестве подкласса. Вот почему вы часто сталкиваетесь с интерфейсами, которые были использованы insted:

 public interface NameAware {
     public String getName();
 }



 class A implements NameAware ...
 class B implements NameAware ...
 class C ... etc. 

Здесь B и C могли бы унаследовать от A, которые бы создали очень высокую связь между ними, используя интерфейсы, связь уменьшилась, если A решит, что больше не будет "NameAware", остальные классы не будут нарушены.

Конечно, если вы хотите повторно использовать поведение, это не сработает.

Ответ 4

вашему BaseClass требуется someString, чтобы доставить его.
Попробуйте следующее:

abstract public class BaseClass {
    String someString;
    public BaseClass(String someString) {
        this.someString = someString;
    }
    abstract public String getName();
}

public class ACSubClass extends BaseClass {
    public ASubClass() {
        super("someString");  // or a meaningfull value, same as getName()?
    }
    public String getName() {
        return "name value for ASubClass";
    }
}

или

abstract public class BaseClass {
    String someString;
    protected BaseClass() {  // for subclasses
        this.someString = null;  // or a meaningfull value
    }
    public BaseClass(String someString) {
        this.someString = someString;
    }
    abstract public String getName();
}

public class ACSubClass extends BaseClass {
    public String getName() {
        return "name value for ASubClass";
    }
}

Ответ 5

Другим способом является вызов super() с требуемым аргументом в качестве первого оператора конструктора производного класса.

public class Sup {
    public Sup(String s) { ...}
}

public class Sub extends Sup {
    public Sub() { super("hello"); .. }
}

Ответ 6

Eclipse предоставит эту ошибку, если у вас нет вызова конструктора суперкласса в качестве первого оператора в конструкторе подкласса.

Ответ 7

эта ошибка возникла из-за неправильной настройки JRE, поэтому выполните следующие действия:


1. щелкните правой кнопкой мыши проект → Свойства → Путь сборки Java → вкладка "Вкладка" Библиотеки "
2. Нажмите Добавить библиотеку
3. Выберите Системную библиотеку JRE → Нажмите "Далее" 4. Выберите "Рабочее пространство" по умолчанию jre или альтернативный установленный jre
5. нажмите "Готово"

Ответ 8

Вы можете решить эту ошибку, добавив конструктор без аргументов в базовый класс (как показано ниже).

Приветствия.

 abstract public class BaseClass {
        // ADD AN ARGUMENTLESS CONSTRUCTOR TO THE BASE CLASS
        public 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";
    }
}

Ответ 9

У меня была эта ошибка и исправлена ​​ее, удалив исключение с исключения из метода в блок try/catch

Например: ОТ:

public static HashMap<String, String> getMap() throws SQLException
{

}

TO:

public static Hashmap<String,String> getMap()
{
  try{

  }catch(SQLException)
  { 
  }
}