2011-08-22 17 views
11

Por favor, hágamelo saber si esto es inapropiado como formulado (en particular, si Programmers.SE o algo sería mejor para la pregunta.)Formas de lograr rasgos efectivos de Java?

Muy bien. Así que tengo una serie de "rasgos" que actualmente estoy expresando como interfaces. Vamos a llamarlos "actualizable" y "destructible". Expresarlos como interfaces tiene la desventaja de que no puedo compartir el comportamiento entre todos los componentes "destructibles"; por el contrario, que expresan estas clases abstractas como decir que no pueda mezclar y combinar sin definir explícitamente el carácter mixto como otra clase abstracta ("UpdateableAndDestructible") y además esto se siente como un abuso de la funcionalidad clase abstracta en ese punto. Es probable que sea lo que terminaré haciendo si no hay maneras más claras de manejar esto, sin embargo.

¿Cuáles son mis opciones en cuanto a soluciones de Java puro para este enigma? ¿Es posible para mí describir el comportamiento compartida y luego mezclar y combinar como lo crea conveniente sin tener que describir explícitamente cada permutación voy a utilizar?

+2

Usted está descibing * * mixins - que podría ser un término útil si está haciendo una buscar. – Jesper

Respuesta

6

Quizás pueda lograr el objetivo utilizando una combinación de interfaces e implementaciones predeterminadas.

igual:

public interface Updatable { 
    void updated(); 
} 

public interface Loadable { 
    void load(); 
} 

public class DefaultUpdatable implements Updatable { 
... 
} 

public class DefaultLoadable implements Loadable { 
... 
} 

public class SomeObject implements Updatable, Loadable { 
    private final Updatable updatable = new DefaultUpdatable(); 
    private final Loadable loadable = new DefaultLoadable(); 

    public void load() { 
    this.loadable.load(); 
    } 

    public void updated() { 
    this.updatable.updated(); 
    } 
} 

Aún ruidoso y quizás no tan flexible como le gustaría pero quizás un poco más limpio que hacer lo UpdatableAndDestructable.

+0

1 y aceptado, esto es una forma sensata de manejar el problema. (Sólo de pasada, mientras que la investigación de este que he encontrado una serie de marcos útiles como Guice que hacen que sea un poco menos dolorosa para usar este tipo de lógica.) –

4

Sé que dijiste "Java puro", pero esto es algo que Scala hace bien. Las limitaciones en el lenguaje Java en sí son un fuerte impulsor para que las personas adopten otros lenguajes JVM ...

+0

Gracias por esta sugerencia. –

5

No creo que haya una solución bonita a este problema, pero tal vez unos pocos viables dependiendo de cuánto desprecien a la repetición.

Puede definir un rasgo como otra clase + interfaz, que toma el objeto de instancia como primer parámetro. Y ellos implementan la interfaz con la clase que desea tener el rasgo. A continuación, cree métodos stub que invoquen los métodos en el rasgo impl.

public class MyClass implements MyTrait { 
    @Override 
    public void doSomething() { 
     MyTraitImpl.doSomething(this); 
    } 
} 

Y luego para el rasgo en sí:

public interface MyTrait { 
    public void doSomething(); 
} 

public class MyTraitImpl { 
    public static void doSomething(MyTrait obj) { 
     // do something with obj 
    } 
} 

Como dice Ernest Friedman-Hill Tho, Scala hace por usted (como yo lo entiendo, esta es la forma en que implementa rasgos en la JVM) .

1

En caso de que considere el uso de lombok como Java puro, se puede simplificar su vida mediante el uso de @Delegate así:

public class SomeObject implements Updatable, Loadable { 
    @Delegate private final Updatable updatable = new DefaultUpdatable(); 
    @Delegate private final Loadable loadable = new DefaultLoadable(); 
}