una resueltos poo metodos metodo interfaces implementación implementacion ejercicios ejemplo crear como clases clase abstractos abstracto abstractas abstracta java generics builder fluent-interface

java - resueltos - metodo abstracto ejemplo



¿Puedo tener una clase de generador abstracto en java con encadenamiento de métodos sin realizar operaciones no seguras? (3)

Estoy tratando de tener una clase base abstracta para algunas clases de constructor para poder reutilizar fácilmente el código entre las implementaciones de Generador. Quiero que mis constructores admitan el encadenamiento de métodos, por lo tanto, un método debe devolver "esta" instancia del tipo más específico. Pensé que probablemente podría hacer esto con los genéricos. Desafortunadamente no logré hacerlo sin utilizar operaciones inseguras. ¿Es posible?

Código de muestra de cómo lo estoy probando (y cómo funciona) a continuación. Me gustaría evitar enviar a T en "foo ()" (lo que provoca una advertencia sin marcar), ¿se puede hacer esto?

public class Builders { public static void main( final String[] args ) { new TheBuilder().foo().bar().build(); } } abstract class AbstractBuilder<T extends AbstractBuilder<?>> { public T foo() { // set some property return (T) this; } } class TheBuilder extends AbstractBuilder<TheBuilder> { public TheBuilder bar() { // set some other property return this; } public Object build() { return new Object(); } }


Desea declarar T como se extends AbstractBuilder<T> en AbstractBuilder .

Utilice un método abstract protected para obtener this de tipo T

abstract class AbstractBuilder<T extends AbstractBuilder<T>> { protected abstract T getThis(); public T foo() { // set some property return getThis(); } } class TheBuilder extends AbstractBuilder<TheBuilder> { @Override protected TheBuilder getThis() { return this; } ... }

Alternativamente, descarte el parámetro de tipo genérico, confíe en los tipos de retorno covariante y haga que el código sea más limpio para los clientes (aunque normalmente usarían TheBuilder lugar de los detalles de implementación en gran medida de la clase base), si se trata de una implementación más detallada.


Esto debería ayudar:

abstract class AbstractBuilder<T extends AbstractBuilder<?>> { public AbstractBuilder<T> foo() { // set some property return (AbstractBuilder<T>) this; } abstract AbstractBuilder<T> bar(); abstract Object build(); }


Una alternativa es no usar genéricos, pero usar reemplazos:

abstract class AbstractBuilder { public AbstractBuilder foo() { // set some property return this; } } class TheBuilder extends AbstractBuilder { @Override public TheBuilder foo() { super.foo(); return this; } public TheBuilder bar() { // set some other property return this; } public Object build() { return new Object(); } }