У меня есть простой код 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
Возможно ли то, что я пытаюсь сделать?
java
inheritance
dry
boilerplate
Джоэл
источник
источник
Ответы:
Вы получаете эту ошибку, потому что класс, у которого нет конструктора, имеет конструктор по умолчанию , который не имеет аргументов и эквивалентен следующему коду:
public ACSubClass() { super(); }
Однако, поскольку ваш BaseClass объявляет конструктор (и, следовательно, не имеет конструктора по умолчанию, no-arg, который в противном случае предоставил бы компилятор), это незаконно - класс, расширяющий BaseClass, не может вызывать
super();
потому что нет конструктора без аргументов в BaseClass.Это, вероятно, немного противоречит интуиции, потому что вы можете подумать, что подкласс автоматически имеет любой конструктор, который имеет базовый класс.
Самый простой способ обойти это - чтобы базовый класс не объявлял конструктор (и, следовательно, имел конструктор по умолчанию без аргументов) или имел объявленный конструктор без аргументов (либо сам по себе, либо вместе с любыми другими конструкторами). Но часто этот подход не может быть применен - потому что вам нужны любые аргументы, передаваемые в конструктор, чтобы создать законный экземпляр класса.
источник
BaseClass
но просто заставить его генерироватьUnsupportedOperationException
или что-то в этом роде. Это не лучшее решение (оно ошибочно предполагает, что класс может поддерживать конструктор без аргументов), но это лучшее, что я могу придумать.Для тех, кто нашел эту ошибку в 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.источник
Это возможно, но не так, как у вас.
Вам нужно добавить в базовый класс конструктор без аргументов, и все!
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 (); и поскольку у вас его нет в суперклассе, вы получите это сообщение об ошибке.
Это о самом вопросе.
Теперь, расширяя ответ:
Вы знаете, что создание подкласса (поведения) для указания другого значения (данных) не имеет смысла ?? !!! Я надеюсь, что да.
Если единственное, что меняется - это "имя", тогда достаточно одного параметризованного класса!
Так что вам это не нужно:
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");
Вот почему наследование - это артефакт, который создает ВЫСОКОЕ сцепление, что нежелательно в объектно-ориентированных системах. Его следует избегать и, возможно, заменить композицией.
Подумайте, действительно ли они вам действительно нужны как подкласс. Вот почему вы часто видите встроенные интерфейсы:
public interface NameAware { public String getName(); } class A implements NameAware ... class B implements NameAware ... class C ... etc.
Здесь B и C могли унаследовать от A, что создало бы очень ВЫСОКУЮ связь между ними, при использовании интерфейсов связь уменьшается, если A решает, что он больше не будет «NameAware», другие классы не сломаются.
Конечно, если вы хотите повторно использовать поведение, это не сработает.
источник
Вы также можете получить эту ошибку, если JRE не установлен. Если да, попробуйте добавить в проект системную библиотеку JRE .
В среде Eclipse IDE:
источник
Другой способ - вызвать super () с обязательным аргументом в качестве первого оператора в конструкторе производного класса.
public class Sup { public Sup(String s) { ...} } public class Sub extends Sup { public Sub() { super("hello"); .. } }
источник
Eclipse выдаст эту ошибку, если у вас нет вызова конструктора суперкласса в качестве первого оператора в конструкторе подкласса.
источник
Извините за некропостинг, но столкнулся с этой проблемой только сегодня. Для всех, кто также сталкивается с этой проблемой - одной из возможных причин - вы не вызываете
super
первую строку метода. Вторая, третья и другие строки вызывают эту ошибку. Вызов super должен быть самым первым вызовом в вашем методе. В этом случае все хорошо.источник
Я решил вышеуказанную проблему следующим образом:
источник
Вы можете решить эту ошибку, добавив к базовому классу конструктор без аргументов (как показано ниже).
Ура.
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"; } }
источник
someString
набора) и, следовательно, полностью сводит на нет цель as конструктора.У меня была эта ошибка, и я исправил ее, удалив выброшенное исключение рядом с методом в блок try / catch
Например: ОТ:
public static HashMap<String, String> getMap() throws SQLException { }
Кому:
public static Hashmap<String,String> getMap() { try{ }catch(SQLException) { } }
источник