2012-04-02 18 views
6

Si consideri il semplice esempio seguente di implementazione di un metodo in un Enum. Un problema con questo metodo è che, quando si hanno molte istanze di enum, non è possibile visualizzarle tutte contemporaneamente come lista. Cioè, se avessimo molti giocattoli, mi piacerebbe vedere "DOLL, SOLDIER, TEDDYBEAR, TRAIN, ETC", insieme, in una lunga lista, e dopo quella lista potrei implementare tutti i metodi necessari, ad es. metodi che sono astratti nell'enum stesso.Java Enum: metodi di implementazione dopo la dichiarazione?

C'è un modo per farlo? O devi implementare i metodi quando dichiari le singole istanze di enum, come nell'esempio qui sotto?

public enum Toy { 
    DOLL() { 
      @Override public void execute() { 
       System.out.println("I'm a doll."); 
      } 
    }, 
    SOLDIER() { 
      @Override public void execute() { 
       System.out.println("I'm a soldier."); 
      } 
    }; 
    //abstract method 
    public abstract void execute(); 
} 
+1

Il modo in cui lo fai sopra è il modo _preferred_ di farlo, FYI. –

+0

Cosa intendi? Secondo quale fonte? – Jonah

+0

Secondo Effective Java. –

risposta

5

Un modo che mi viene in mente è quello di lasciare l'attuazione dei metodi astratti per separare classi di implementazione, qualcosa di simile:

interface ToyBehaviour { 

    void execute(); 
} 

public enum Toy { 
    DOLL(new DollBehaviour()), 
    SOLDIER(new SoldierBehaviour()); 

    private final ToyBehaviour behaviour;  

    Toy(ToyBehaviour impl) { 

     behaviour = impl; 
    } 

    public void execute() { 

     behaviour.execute(); 
    } 
} 

class DollBehaviour implements ToyBehaviour { 

    public void execute() { 
     System.out.println("I'm a doll."); 
    } 
} 

Questa configurazione permetterebbe di creare classi di comportamento in file separati, nel caso che l'implementazione ha abbastanza complessità da giustificare la separazione.

Nel caso in cui l'applicazione è abbastanza semplice da includere in quello enum classe, è possibile mettere le classi di interfaccia e comportamento come figli della classe enum:

public enum Toy { 
    // enum values 
    DOLL(new DollBehaviour()), 
    SOLDIER(new SoldierBehaviour()); 

    private final ToyBehaviour behaviour;  

    Toy(ToyBehaviour impl) { 

     behaviour = impl; 
    } 

    public void execute() { 

     behaviour.execute(); 
    } 

    // behaviour interface 
    interface ToyBehaviour { 

     void execute(); 
    } 

    // behaviour implementation (sub)classes 
    static class DollBehaviour implements ToyBehaviour { 

     public void execute() { 
      System.out.println("I'm a doll."); 
     } 
    } 

    // etc ... 
} 

avrei probabilmente optare per il prima implementazione, a meno che la gerarchia delle classi di implementazione sia molto banale.

4

Se vuoi dichiarazioni enum più compatti, gli unici modi che posso pensare di farlo sono:

se è possibile costruire i vostri metodi di variabili di inizializzazione:

public enum Toy { 
    DOLL("doll"),SOLDIER("soldier"); 

    private Toy(String name){ this.name=name;} 
    public void execute(){ System.out.println("I'm a "+name);} 
} 

o , leggermente più complicato, simile allo stesso con funzioni, se il comportamento è più complesso -

abstract class SomeToyMethod { 
    abstract void execute(); 

    public SomeToyMethod DOLL_METHOD = new SomeToyMethod(){ 
    public void execute(){ System.out.println("I'm a doll");}) 
    public SomeToyMethod SOLDIER_METHOD = new SomeToyMethod(){ 
    public void execute(){ System.out.println("I'm a soldier");}) 


public enum Toy { 
    DOLL(SomeToyMethod,DOLL_METHOD),SOLDIER(SomeToyMethod.SOLDIER_METHOD); 

    private Toy(SomeToyMethod method){ this.method=method;} 
    public void execute(){ method.execute();} 
} 
+1

"Non è possibile dichiarare metodi astratti in enumerazione". Non vero. – darrengorman

+0

Ah, hai ragione - il mio compilatore in realtà dice che è permesso solo se dichiari enum che implementano il metodo astratto. Grazie per la correzione, correggerò quanto sopra. –

+0

I metodi astratti in enumerazione sono perfettamente legali. – Yanflea

2

Si potrebbe provare qualcosa di simile:

public enum Toy { 
    DOLL, 
    SOLDIER, 
    ANOTHER_TOY; 

    public static void execute(Toy toy) { 
     switch(toy) { 
      case DOLL: 
       System.out.println("I'm a doll."); 
       break; 
      case SOLDIER: 
       System.out.println("I'm a soldier."); 
       break; 
      case ANOTHER_TOY: 
       System.out.println("I'm another toy."); 
       break; 
     } 
    } 
} 

Non molto bella, ma mantiene le dichiarazioni enum insieme.

+0

latte, divertente, in realtà ci ho pensato, e data la semplicità dei miei comportamenti modello funzionerebbe bene, ma questo non mi darà un colpo di prestazioni? Userò queste enumerazioni nel contesto di simulazioni (milioni di accessi), quindi ho pensato che le ricerche "caso:" avrebbero rallentato il programma un po '... cosa ne pensi? – Jonah

+0

Si noti che questo rimuove efficacemente l'incapsulamento/polimorfismo offerto dall'originale. –

+1

Nota, è possibile rimuovere statico e parametro e accendere invece 'this'. Le affermazioni del caso sono veloci. Mi piace farlo, ma solo quando l'interruttore è definito nell'enum stesso e solo se le diverse opzioni sono one-liner. – ILMTitan

Problemi correlati