2012-04-02 2 views
6

Рассмотрим простой пример реализации метода в Enum. Одна из проблем с этим методом заключается в том, что, когда у вас много экземпляров enum, вы визуально больше не можете видеть их всех сразу, как список. То есть, если бы у нас было много игрушек, я бы хотел увидеть «ДОЛЛ, СОЛДАТ, ТЕДДЬЮБЕР, ТРЕЙН И ЕТК» вместе в одном длинном списке, а затем после этого списка я мог бы реализовать любые необходимые методы, например. методы, которые являются абстрактными в самом перечислении.Переменные Java: методы реализации После объявления?

Есть ли способ сделать это? Или вам нужно реализовать методы, когда вы объявляете отдельные экземпляры enum, как в примере ниже?

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

Как вы это делаете, это способ _preferred_ сделать это, FYI. –

+0

Что значит? По какому источнику? – Jonah

+0

Согласно эффективной Java. –

ответ

5

Один из способов, который приходит на ум, чтобы оставить реализацию абстрактных методов для разделения классов реализации, что-то вроде:

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

Эта установка позволит вам создавать классы поведения в отдельных файлах в том случае, если есть ваша реализация достаточная сложность для обеспечения разделения.

В случае, реализация достаточно просто включить его в одну 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 ... 
} 

я бы, вероятно, выбрать для первая реализация сама, если иерархия классов реализации очень тривиальна.

4

Если вы хотите более компактные объявления перечислений, единственными способами я могу думать о том, чтобы сделать это, являются:

, если вы можете построить свои методы из инициализаторов переменных:

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

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

или , несколько сложнее, то же самое с функциями, если поведение более сложное -

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

'Вы не можете объявлять абстрактные методы в перечислениях. Не правда. – darrengorman

+0

Ах, вы правы - мой компилятор на самом деле говорит, что разрешено только, если вы объявляете перечисления, реализующие абстрактный метод. Спасибо за исправление, исправьте вышеизложенное. –

+0

Абстрактные методы в перечислениях являются совершенно законными. – Yanflea

2

Вы могли бы попробовать что-то вроде:

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

Не очень красиво, но она сохраняет свои объявления перечислений вместе.

+0

молоко, смешно, я действительно подумал об этом, и, учитывая простоту поведения моего шаблона, он будет работать нормально, но разве это не даст мне удар по производительности? Я буду использовать эти перечисления в контексте симуляции (миллионы хитов), поэтому я подумал, что поиск «case:» замедлит программу немного ... как вы думаете? – Jonah

+0

Обратите внимание, что это эффективно удаляет инкапсуляцию/полиморфизм, предлагаемый оригиналом. –

+1

Обратите внимание: вы можете удалить статический и параметр и вместо этого включить 'this'. Заявления о делах бывают быстрыми. Мне нравится делать это, но только тогда, когда переключатель определен в самом перечислении, и только если разные параметры являются однострочными. – ILMTitan

Смежные вопросы