2016-01-30 2 views
2

Я хочу, чтобы иметь возможность подклассифицировать некоторые значения в перечислении, чтобы мне не пришлось слишком много повторять код. Есть ли способ сделать это? Вот пример того, что я хочу достичь, что Eclipse, быстро говорит мне это мерзость:Подклассификация значения перечисления

public enum Foo { 
    BAR { 
     @Override 
     public void taskA() { 
      System.out.println("A"); 
     } 

     @Override 
     public void taskB() {} 
    }, 
    BAZ extends BAR { 
     @Override 
     public void taskB() { 
      System.out.println("B"); 
     } 
    }; 

    public abstract void taskA(); 
    public abstract void taskB(); 
} 

BAR будет иметь только реализацию taskA и пустой taskB и BAZ бы оба метода - реализация BAR «s от taskA и собственной реализации taskB.

Я не изменяю значения перечисления после его объявления, так почему же это не работает? Я мог бы позвонить BAR в taskA методе в пределах BAZ, так почему я не могу это сделать?

+0

Можете ли вы использовать Java8? – slartidan

+0

@slartidan Я не могу, но ваш пример ниже полезен для всех, у кого может быть такая же проблема. –

ответ

2

Enum-Constants - это объекты (экземпляры), а не классы. Вы можете использовать только классы подкласса.

Однако даже это не сработает: вы можете расширять только перечисления с помощью любых внутренних классов.

Вам понадобится найти другое решение для вашего случая использования. Вы могли бы:

  • использовать статический метод для общего кода
  • вызова BAR.taskA() в БАЗЕ
  • сделать Таску не абстрактным и поставить свой код там
  • использовать обычные константы, вместо перечислений

Но мой приоритет:

  • в ject, а не переопределение!

Пример код:

class Behavior { 
    public static Runnable A = new Runnable() { 
     public void run() { 
      System.out.println("A"); 
     } 
    } 

    public static Runnable B = new Runnable() { 
     public void run() { 
      System.out.println("B"); 
     } 
    } 

    public static Runnable DO_NOTHING = new Runnable() { 
     public void run() { 
     } 
    } 
} 

public enum Foo { 
    BAR(Behavior.A, Behavior.DO_NOTHING), 
    BAZ(Behavior.A, Behavior.B); 

    private final Runnable mechanismA; 
    private final Runnable mechanismB; 

    private Foo(Runnable mechanismA, Runnable mechanismB) { 
     this.mechanismA = mechanismA; 
     this.mechanismB = mechanismB; 
    } 

    public void taskA() { 
     mechanismA.run; 
    } 

    public void taskB() { 
     mechanismB.run; 
    } 
} 

Достоинство этого решения:

  • Код явно определяет поведение каждой константы перечислимой - нет неявных расчетов => проще не читать
  • Вы можете использовать наследование и т. Д. В классе поведения
  • Вы можете легко переключаться behaviorA и behaviorB - или повторное этот код нигде

Если у вас есть Java8 доступных вы можете даже сократить код для этого:

public static Runnable A =() -> { 
    System.out.println("A"); 
}; 
+0

Фактически, константы перечисления, которые переопределяют метод абстрактного перечисления (например, BAR.taskA в вопросе), являются экземплярами анонимных подклассов этого перечисления. –

+1

Это может выглядеть немного чище, если вы используете lambdas вместо Runnables (хотя это уже хорошо, как есть). –

2

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

Обычный способ совместного использования кода среди постоянных конкретных методов, чтобы объявить частный статический метод (либо в самом или в грузопассажирских вспомогательный класс перечислимого), который содержит общий код, который вы хотите получить доступ из вашей постоянной -специфические методы.

Например ...

public enum Foo { 
    BAR { 
     @Override 
     public void taskA() { 
      commonToTaskAandB(); 
      System.out.println("B"); 
     } 

     @Override 
     public void taskB() {} 
    }, 
    BAZ { 
     @Override 
     public void taskB() { 
      commonToTaskAandB(); 
      System.out.println("B"); 
     } 
    }; 

    public abstract void taskA(); 
    public abstract void taskB(); 

    private static void commonToTaskAandB() { 
     // shared code here 
     : 
     : 
    } 

}

Обратите внимание, что код "BAZ extends Bar" является незаконным, поскольку БАЗ не является типом. BAZ - это экземпляр вашего типа Enum<Foo>. Экземпляр не может распространять другой тип. Неправильно применять объектно-ориентированные принципы, такие как наследование констант перечисления, потому что в Java константы перечисления являются экземплярами класса, а не сами классы.

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