Tengo un código Java simple que se parece a esto en su estructura:
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";
}
}
Tendré bastantes subclases de BaseClass
, cada una implementando el getName()
método a su manera ( patrón de método de plantilla ).
Esto funciona bien, pero no me gusta tener el constructor redundante en las subclases. Es más para escribir y es difícil de mantener. Si BaseClass
tuviera que cambiar la firma del método del constructor, tendría que cambiar todas las subclases.
Cuando elimino el constructor de las subclases, obtengo este error en tiempo de compilación:
Implicit super constructor BaseClass() is undefined for default constructor. Must define an explicit constructor
¿Es posible lo que estoy tratando de hacer?
java
inheritance
dry
boilerplate
Joel
fuente
fuente
Respuestas:
Obtiene este error porque una clase que no tiene constructor tiene un constructor predeterminado , que no tiene argumentos y es equivalente al siguiente código:
public ACSubClass() { super(); }
Sin embargo, dado que su BaseClass declara un constructor (y, por lo tanto, no tiene el constructor predeterminado sin argumentos que el compilador proporcionaría de otra manera), esto es ilegal: una clase que extiende BaseClass no puede llamar
super();
porque no hay un constructor sin argumentos en BaseClass.Esto probablemente sea un poco contrario a la intuición porque podría pensar que una subclase tiene automáticamente cualquier constructor que tenga la clase base.
La forma más sencilla de evitar esto es que la clase base no declare un constructor (y por lo tanto tenga el constructor no-arg predeterminado) o tenga un constructor declarado no-arg (ya sea por sí mismo o junto con cualquier otro constructor). Pero a menudo este enfoque no se puede aplicar, porque necesita los argumentos que se pasen al constructor para construir una instancia legítima de la clase.
fuente
BaseClass
pero hágalo simplemente lanzar unUnsupportedOperationException
o algo. No es la mejor solución (sugiere falsamente que la clase puede admitir un constructor sin argumentos), pero es la mejor que se me ocurre.Para aquellos que buscan en Google este error y llegan aquí: puede haber otra razón para recibirlo. Eclipse da este error cuando tiene la configuración del proyecto: la configuración del sistema no coincide.
Por ejemplo, si importa el proyecto Java 1.7 a Eclipse y no tiene 1.7 configurado correctamente, obtendrá este error. A continuación, puede ir a cualquiera
Project - Preference - Java - Compiler
yswitch to 1.6 or earlier
; o vaya aWindow - Preferences - Java - Installed JREs
y agregue / arregle su instalación de JRE 1.7.fuente
Es posible, pero no de la forma en que lo tiene.
¡Tienes que agregar un constructor sin argumentos a la clase base y eso es todo!
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"; } }
Cuando no agrega un constructor (cualquiera) a una clase, el compilador agrega el constructor predeterminado sin arg para usted.
Cuando el defualt no arg llama a super (); y como no lo tiene en la superclase, aparece ese mensaje de error.
Esa es la pregunta en sí misma.
Ahora, ampliando la respuesta:
¿Es consciente de que crear una subclase (comportamiento) para especificar un valor (datos) diferente no tiene sentido? Espero que lo hagas.
Si lo único que cambia es el "nombre", ¡una sola clase parametrizada es suficiente!
Entonces no necesitas esto:
MyClass a = new A("A"); MyClass b = new B("B"); MyClass c = new C("C"); MyClass d = new D("D");
o
MyClass a = new A(); // internally setting "A" "B", "C" etc. MyClass b = new B(); MyClass c = new C(); MyClass d = new D();
Cuando puedes escribir esto:
MyClass a = new MyClass("A"); MyClass b = new MyClass("B"); MyClass c = new MyClass("C"); MyClass d = new MyClass("D");
Bueno, es por eso que la herencia es el artefacto que crea un acoplamiento ALTO, lo cual no es deseable en los sistemas OO. Debería evitarse y quizás reemplazarse con composición.
Piense si realmente los necesita como subclase. Es por eso que ve muy a menudo que se usan interfaces en:
public interface NameAware { public String getName(); } class A implements NameAware ... class B implements NameAware ... class C ... etc.
Aquí B y C podrían haber heredado de A lo que habría creado un acoplamiento muy ALTO entre ellos, al usar interfaces el acoplamiento se reduce, si A decide que ya no será "NameAware", las otras clases no se romperán.
Por supuesto, si desea reutilizar el comportamiento, esto no funcionará.
fuente
También puede obtener este error cuando JRE no está configurado. Si es así, intente agregar la biblioteca del sistema JRE a su proyecto.
Bajo Eclipse IDE:
fuente
Otra forma es llamar a super () con el argumento requerido como primera declaración en el constructor de la clase derivada.
public class Sup { public Sup(String s) { ...} } public class Sub extends Sup { public Sub() { super("hello"); .. } }
fuente
Eclipse dará este error si no tiene una llamada al constructor de superclase como primera declaración en el constructor de subclase.
fuente
Lo siento por necropostar pero enfrenté este problema hoy Para todos los que también enfrentan este problema, una de las posibles razones, no se llama
super
a la primera línea del método. La segunda, la tercera y otras líneas disparan este error. La llamada de super debe ser la primera llamada en su método. En este caso todo va bien.fuente
He resuelto el problema anterior de la siguiente manera:
fuente
Puede resolver este error agregando un constructor sin argumentos a la clase base (como se muestra a continuación).
Salud.
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"; } }
fuente
someString
) un conjunto y, por lo tanto, frustra totalmente el propósito de como constructor.Tuve este error y lo solucioné eliminando una excepción lanzada al lado del método a un bloque try / catch
Por ejemplo: DE:
public static HashMap<String, String> getMap() throws SQLException { }
A:
public static Hashmap<String,String> getMap() { try{ }catch(SQLException) { } }
fuente