Указывая, что параметр абстрактного метода должен быть перечислением - PullRequest
0 голосов
/ 22 марта 2012

Я пишу абстрактный класс на Java, где я бы хотел, чтобы параметр одного из моих абстрактных методов был перечислением, поэтому я получил следующее. Обратите внимание, что только подклассы будут знать, какие возможные состояния он может иметь. (Прошу прощения за надуманный пример)

public abstract class StateTracker {
    public abstract boolean isInState(???????? state);
}

Что такое ????????? В этом и заключается проблема:

  • В идеале это было бы абстрактное перечисление с именем StateEnum, которое не имеет экземпляров, и клиенты StateTracker могли бы создавать свои собственные конкретные StateEnums. Но мы не можем сделать ничего подобного в Java.
  • Я мог бы сделать это интерфейсом, но тогда у меня не было бы способа гарантировать, что подклассы реализуют его как перечисление, что является целью.
  • Я мог бы изменить его на Enum <? > . Я пытаюсь это сделать, и в моем подклассе я делаю что-то вроде этого:

    public class MyStateTracker extends StateTracker {
    
        public enum MyState {
             BADSTATE_1, BADSTATE_2
        }
    
        @Override
        public boolean isInState(?!?!?!?! state) {
             // TODO Auto-generated method stub
        return false;
     }
    
    }
    

Теперь, что такое?!?!?!?! Вот возможности:

  • MyState. Это не компилируется, так как не думает, что я переопределяю абстрактный метод.
  • Enum. Та же проблема.

Как я могу убедиться, что конкретные классы используют emum?

Ответы [ 3 ]

4 голосов
/ 22 марта 2012

Это зависит от того, хотите ли вы иметь возможность спросить StateTracker, находится ли он в состояниях, объявленных различными enum типами.

Если вы хотите заблокировать состояния так, чтобы данный трекер состояний можно было запрашивать только для одного типа enum, создайте универсальный тип:

interface StateTracker<S extends Enum<S>> {
  boolean isInState(S state);
}

final class MyStateTracker implements StateTracker<MyStateTracker.MyState> {
  enum MyState { S1, S2 };
  private MyState state;
  ...
  @Override
  public boolean isInState(MyState state) {
    return state == this.state;
  }
}

Если у вас есть пара enum типов, определяющих состояния, подобные этому:

enum MyState { S1, S2 }
enum YourState { S1, S2 };

& hellip; и вы хотите иметь возможность спросить StateTracker, находится ли он в каком-либо состоянии (определенном любым enum, на самом деле, если только вы не объявите интерфейс маркера State для реализации enum), а затем создайте универсальный метод:

interface StateTracker {
  <S extends Enum<S>> boolean isInState(S state);
}
3 голосов
/ 22 марта 2012
class StateTracker<E extends Enum<E>> {
  public abstract boolean isInState(E state);
}
1 голос
/ 22 марта 2012

Для этого можно использовать обобщенные формы, все перечисления Java неявно расширяются java.lang.Enum :

abstract class StateTracker<T extends Enum<?>> {
    public abstract boolean isInState(T state);
}

enum MyState {
    State_1, State_2
}

class State extends StateTracker<MyState>
{
    private MyState currentState = MyState.State_2;

    @Override
    public boolean isInState(MyState state)
    {
        return state.equals(currentState);
    }
}

public class TestEnum
{
    @Test
    public void testIsInState()
    {
        State state = new State();
        Assert.assertFalse(state.isInState(MyState.State_1));
        Assert.assertTrue(state.isInState(MyState.State_2));
    }
}

//This won't compile, so the generic-type must be an Enum
/*
class State2 extends StateTracker<String> //<-- Bound mismatch: The type String is not a valid substitute for the bounded parameter <T extends Enum<?>> of the type StateTracker<T>
{
    @Override
    public boolean isInState(String state)
    {
        // TODO Auto-generated method stub
        return false;
    }   
}
*/
...