2011-08-22 2 views
11

S'il vous plaît laissez-moi savoir si cela est inapproprié comme formulé (en particulier si Programmers.SE ou quelque chose serait mieux pour la question.)Comment obtenir des traits Java efficaces?

D'accord. J'ai donc un certain nombre de «traits» que j'exprime actuellement en tant qu'interfaces. Appelons-les "updatable" et "destructible". Les exprimer en tant qu'interfaces a l'inconvénient que je ne peux pas partager le comportement entre tous les composants "destructibles"; d'autre part, les exprimer en tant que classes abstraites signifie que je ne peux pas mélanger et assortir sans définir explicitement le trait mixte comme une autre classe abstraite ("UpdateableAndDestructible") et de plus cela ressemble à un abus de la fonctionnalité de classe abstraite à ce point. C'est probablement ce que je finirai par faire s'il n'y a pas des façons plus propres de gérer cela.

Quelles sont mes options en ce qui concerne les solutions purement Java à cette énigme? Est-il possible pour moi de décrire un comportement partagé puis de mélanger et d'apparier comme je le souhaite sans avoir à décrire explicitement chaque permutation que j'utiliserai?

+2

Vous descibing * mixins * - qui pourrait être un terme utile si vous faites une chercher. – Jesper

Répondre

6

Vous pourriez peut-être atteindre cet objectif en utilisant un mélange d'interfaces et d'implémentations par défaut.

Comme:

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(); 
    } 
} 

Toujours bruyant et peut-être pas aussi flexible que vous le souhaitez, mais peut-être un peu plus propre que de faire la chose UpdatableAndDestructable.

+0

+1 et accepté, c'est une façon sensée de gérer le problème. (En passant, tout en enquêtant sur ce sujet, j'ai trouvé un certain nombre de cadres utiles comme Guice qui rendent un peu moins douloureux d'utiliser ce genre de logique.) –

4

Je sais que vous avez dit "Java pur", mais c'est quelque chose que fait Scala. Les limitations dans le langage Java lui-même sont un puissant moteur d'adoption d'autres langages JVM ...

+0

Merci pour cette suggestion. –

5

Je ne pense pas qu'il y ait une jolie solution à ce problème, mais peut-être quelques-uns réalisables en fonction de combien vous méprisez le passe-partout.

Vous pouvez définir un trait comme une autre classe + interface, qui prend l'objet d'instance comme premier paramètre. Et ils implémentent l'interface avec la classe que vous voulez avoir le trait. Ensuite, créez des méthodes stub qui appellent les méthodes sur l'attribut trait.

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

Et puis pour le trait lui-même:

public interface MyTrait { 
    public void doSomething(); 
} 

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

Comme Ernest Friedman-Hill dit tho, Scala fait pour vous (si je comprends bien, voici comment elle met en œuvre des traits sur la machine virtuelle Java) .

1

Si vous envisagez d'utiliser lombok comme Java pur, vous pouvez simplifier votre vie en utilisant @Delegate comme ceci:

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