tutorial interfaz grafica español ejemplos componentes java methods field abstract

interfaz - java jframe tutorial pdf



¿Por qué no campos abstractos? (6)

Al leer su título, pensé que se estaba refiriendo a los miembros de la instancia abstracta; y no pude ver mucho uso para ellos. Pero los miembros estáticos abstractos son otra cosa completamente diferente.

A menudo he deseado poder declarar un método como el siguiente en Java:

public abstract class MyClass { public static abstract MyClass createInstance(); // more stuff... }

Básicamente, me gustaría insistir en que las implementaciones concretas de mi clase principal proporcionen un método de fábrica estático con una firma específica. Esto me permitiría obtener una referencia a una clase concreta con Class.forName() y estar seguro de que podría construir uno en una convención de mi elección.

¿Por qué las clases Java no pueden tener campos abstractos como pueden tener métodos abstractos?

Por ejemplo: tengo dos clases que extienden la misma clase base abstracta. Estas dos clases tienen cada una un método que es idéntico, excepto por una constante de cadena, que resulta ser un mensaje de error, dentro de ellas. Si los campos pudieran ser abstractos, podría hacer este resumen constante e incorporar el método a la clase base. En cambio, tengo que crear un método abstracto, llamado getErrMsg() en este caso, que devuelve el String, anula este método en las dos clases derivadas, y luego puedo extraer el método (que ahora llama al método abstracto).

¿Por qué no podría simplemente hacer el campo abstracto para empezar? ¿Podría Java haberse diseñado para permitir esto?


No veo sentido en eso. Puede mover la función a la clase abstracta y simplemente anular algún campo protegido. No sé si esto funciona con constantes, pero el efecto es el mismo:

public abstract class Abstract { protected String errorMsg = ""; public String getErrMsg() { return this.errorMsg; } } public class Foo extends Abstract { public Foo() { this.errorMsg = "Foo"; } } public class Bar extends Abstract { public Bar() { this.errorMsg = "Bar"; } }

¿Entonces tu punto es que quieres aplicar la implementación / anulación / lo que sea de errorMsg en las subclases? Pensé que solo querías tener el método en la clase base y no sabías cómo lidiar con el campo entonces.


Obviamente, podría haber sido diseñado para permitir esto, pero bajo las cubiertas todavía tendría que hacer despacho dinámico, y por lo tanto una llamada a un método. El diseño de Java (al menos en los primeros días) fue, hasta cierto punto, un intento de ser minimalista. Es decir, los diseñadores trataron de evitar agregar nuevas características si pudieran ser fácilmente simuladas por otras características que ya estaban en el idioma.


Otra opción es definir el campo como público (final, si lo desea) en la clase base, y luego inicializar ese campo en el constructor de la clase base, dependiendo de qué subclase esté siendo utilizado actualmente. Es un poco sospechoso, ya que introduce una dependencia circular. Pero, al menos, no es una dependencia que puede cambiar, es decir, la subclase existirá o no existirá, pero los métodos o campos de la subclase no pueden influir en el valor del field .

public abstract class Base { public final int field; public Base() { if (this instanceof SubClassOne) { field = 1; } else if (this instanceof SubClassTwo) { field = 2; } else { // assertion, thrown exception, set to -1, whatever you want to do // to trigger an error field = -1; } } }


Podría definir un constructor parametrizado en la clase abstracta.

De esta forma, las subclases se ven obligadas a definir sus propios constructores y llamar al super constructor, algo como lo siguiente:

public abstract class TransactionManager { private String separator; public TransactionManager(String separator) { this.separator = separator; } }

Entonces tu clase concreta se vería así:

public class TransactionManagerFS extends TransactionManager{ // The IDE forces you to implement constructor. public TransactionManagerFS(String separator) { super(separator); } }

Ver ejemplo completo desde here .


Puede hacer lo que describió al tener un campo final en su clase abstracta que se inicializa en su constructor (código no probado):

abstract class Base { final String errMsg; Base(String msg) { errMsg = msg; } abstract String doSomething(); } class Sub extends Base { Sub() { super("Sub message"); } String doSomething() { return errMsg + " from something"; } }

Si la clase de su hijo "olvida" inicializar la final a través del superconstructor, el compilador dará un error de advertencia , al igual que cuando no se implementa un método abstracto.