2012-04-02 19 views
6

Considere el ejemplo simple a continuación de implementar un método en un Enum. Un problema con este método es que, cuando tiene muchas instancias enum, visualmente ya no puede verlas todas a la vez, como una lista. Es decir, si tuviéramos muchos juguetes, me gustaría ver "DOLL, SOLDIER, TEDDYBEAR, TRAIN, ETC", juntos, en una larga lista, y luego de esa lista podría implementar cualquier método necesario, p. métodos que son abstractos en la enumeración misma.Java Enums: Implementing methods After Declaration?

¿Hay alguna manera de hacer esto? ¿O tiene que implementar los métodos cuando declara las instancias enum individuales, como en el ejemplo a continuación?

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

La forma de hacerlo es la _preferred_ forma de hacerlo, FYI. –

+0

¿Qué quieres decir? De acuerdo a que fuente? – Jonah

+0

De acuerdo con Java efectivo. –

Respuesta

5

Una manera en que viene a la mente es salir de la aplicación de los métodos abstractos para separar las clases de implementación, algo así como:

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."); 
    } 
} 

Esta configuración le permitirá crear clases de comportamiento en archivos independientes en el caso de que su aplicación tiene suficiente complejidad para garantizar la separación.

En el caso de que la aplicación es lo suficientemente simple para incluirlo en el enum clase, puede poner las clases de interfaz y de comportamiento como los niños de la clase de enumeración:

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 ... 
} 

que probablemente optar por el primera implementación yo mismo, a menos que la jerarquía de las clases de implementación sea muy trivial.

4

Si desea declaraciones de enumeración más compactas, las únicas formas que se me ocurre para hacerlo son:

si se puede construir sus métodos de variables de inicializador:

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 y algo más complicada, tipo de la misma con las funciones, si el comportamiento es más compleja -

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

'No puede declarar métodos abstractos en enums'. No es verdad. – darrengorman

+0

Ah, estás en lo cierto: mi compilador dice que solo está permitido si declaras enumeraciones que implementan el método abstracto. Gracias por la corrección, corregirá lo anterior. –

+0

Los métodos abstractos en las enumeraciones son perfectamente legales. – Yanflea

2

Usted podría intentar algo como:

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

No es muy bonita, pero que mantiene sus declaraciones de enumeración juntos.

+0

leche, gracioso, realmente pensé en eso, y dada la simplicidad de mis comportamientos de plantilla, funcionaría bien, pero ¿no me daría esto un golpe de rendimiento? Usaré estas enumeraciones en el contexto de las simulaciones (millones de visitas), así que pensé que las búsquedas de "caso:" retrasarían un poco el programa ... ¿qué piensas? – Jonah

+0

Tenga en cuenta que esto elimina efectivamente la encapsulación/polimorfismo ofrecido por el original. –

+1

Nota: puede eliminar la estática y el parámetro, y activar 'this' en su lugar. Las declaraciones de casos son rápidas. Me gusta hacer esto, pero solo cuando el interruptor está definido en la enumeración en sí, y solo si las diferentes opciones son de una sola línea. – ILMTitan