2017-02-20 42 views
0

G'day, я стремился создать абстрактный (базовый) класс extend -ing EnumMap. У меня уже есть прототип кода, который отлично работает на основе подкласса EnumMap, и я хочу преобразовать его в общую базу, которую я могу использовать с разными типами Enum (то есть общий Enum<K>).Как создать общий класс Enum <K>, который расширяет EnumMap и вызывает super (K.class)?

Дорога-блок я ударил это ...

  • Как рассказать EnumMap конструктор класса родового Enum<K>?

Для сравнения рабочий (не общий) класс выглядеть следующим образом, учитывая Enum<States>:

public class MyMap extends EnumMap<States, FocusTraversalPolicy> 
    { 
     private static States DEFAULT_POLICY; 
     private static States currentPolicy = DEFAULT_FLOW; 

     public MyMap(){ 
      this(States.DATA_INPUT); 
     } 

     public MyMap (final ProcessState defaultPolicy ){ 

      super(States.class); 

      DEFAULT_POLICY = defaultPolicy; 
      currentPolicy = DEFAULT_FLOW; 
     } 
    } 

Моя способность переводить это в дженерика ударил набор альтернативных ошибок, закипает вплоть до сложности передачи типа Enum (K.class) в родительский конструктор EnumMap, а именно:

Cannot select from type variable 

и (кратко)

No suitable constructor found ... 
argument mismatch; Class<CAP#1> cannot be converted to Class<K>) 

Моя декларация до сих пор выглядит следующим образом:

public abstract class MapBase<K> extends EnumMap<K, FocusTraversalPolicy>{ 

     private K DEFAULT_POLICY; 
     private K currentPolicy; 

     private Enum Dummy { 
      NOTHING 
     } 

     private MapBase() {  // disable empty constructor 
      this(Dummy.NOTHING); // Exclude NullPointerException-s 
     } 

     public MapBase(final K defaultPolicy) // Default compulsory 
     { 
      super(K.class);     // <-- Cannot select from type variable 
               // OR 
      super(defaultPolicy.getClass()); // <-- No suitable constructor found 

      DEFAULT_POLICY = defaultPolicy; 
      currentPolicy = DEFAULT_FLOW; 
     } 
    } 

Это, насколько я получил. Я попытался несколько вариантов с более или менее разными способами сказать мне то же самое, например.

class MapBase<K extends Enum<K>> 
     extends EnumMap<K, FocusTraversalPolicy>{ 
      : 
    } 

В то время как версия универсалов для базового класса является наиболее желательной, кажется, что это может быть невозможно; или что я не следую правильному синтаксису, чтобы сделать «вид« базового класса, который я хочу.

Даже если знать, если «Вы не можете этого сделать.« Полезен, и я отвлеку свои усилия на другую структуру. Это просто кажется более OO до inherit против повторного изобретения совершенно хорошего существующего прототипа колеса. Я очень благодарен.

+1

Я исправил ваше форматирование. Пожалуйста, обратите внимание на предварительный просмотр при редактировании и просмотрите сообщение после сохранения. –

+1

Это выглядит серьезно неправильно: расширение EnumMap с использованием одного (то есть делегирование EnumMap), использование заглавного поля без конца в all-caps, инициализация статического поля из конструктора, попытка размещения экземпляра Dummy в переменной типа K Забудьте о своем желаемом дизайне какое-то время и сообщите нам, чего вы пытаетесь достичь, потому что, вероятно, лучший способ. –

+0

Что относительно состава над наследованием? – efekctive

ответ

1

Вопиющая проблема с кодом является очевидным ненадлежащим использованием наследования. Вы вряд ли сбережете много памяти, и код станет беспорядочным.

Так начало класса становится

public class TraversalPolicies<K extends Enum<K>> { 
    private final Map<K, FocusTraversalPolicy> policies; 

Конструктор EnumMap нуждается в Class о перечислении, потому что он будет делать что-то в стиле фанк индексации порядковое в массив значений.

Простым было это сделать объект Class, переданный вашему родовому классу.

public TraversalPolicies(Class<K> clazz) { 
     this.policies = new EnumMap<>(clazz); 

В качестве альтернативы, Class может быть взят из экземпляра перечисления, если у вас есть один доступный.

public TraversalPolicies(K defaultPolicy) { 
     this.policies = new EnumMap<>(defaultPolicy.getDeclaringClass()); 
+0

Интересная альтернатива, та. Но политика не относится к типу - . Требование состоит в том, чтобы различные значения перечисления в MAP были определены политиками. Этот код работает, он очень прост и проверен. Желательно сделать базовый код _generic_ (small g). Это все_. – will

+1

Я не следую. В вашем коде были переменные политики, имеющие тип 'K', который использовался как ключ для« EnumMap », поэтому его следует было объявить как« K extends Enum ». Уменьшение размера исходного кода с помощью оппортунистического наследования крошечное и не стоит того беспорядка, который он создает. –

+0

В текущем коде отсутствует '_mess_'. Он очень доволен; для около 17 строк мы получаем двунаправленный полевой менеджер Enum. – will

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