枚举抽象问题

时间:2011-04-04 13:19:57

标签: java enums abstraction

我目前正在努力解决java抽象问题。我有这样的事情:

public interface State {
};

public interface Dynamics {
  getObservationChance(State state, Observation observation);
};

class SpecialState implements State {
};

enum SpecialObservation() {
  FREE, WALL, etc.
}

class SpecialDynamics implements Dynamics {
   getObservationChance(State state, Observation observation) {
       // state should be SpecialState, observation should be SpecialObservation!
   }
};

class Main {
  Main(State state, Observation observation, Dynamics dynamics) {
      dynamics.getObservationChance(state, observation);
   }
};

SecialObservation应该是可能观察的枚举(或类似的东西),但我希望对问题进行抽象表示。所以我想要一个观察应该包含观察一个函数,该函数返回所有可能观察的列表。最后一件事对于我正在实施的算法非常重要,因为我必须总结所有可能的观察结果。

谢谢!

4 个答案:

答案 0 :(得分:3)

这里需要参数化类型 - 每个树类型都有:状态,观察和动态。

如果我们将观察枚举作为参数类型,我们可以将您的类型转换为这样的类型:

public interface Observation<O extends Observation<O>> {
    ...
}

public interface State<O extends Observation<O>> {
}

public interface Dynamics<O extends Observation<O>> {
  getObservationChance(State<O> state, O observation);
}

enum SpecialObservation implements Observation<SpecialObservation> {
  FREE, WALL, etc.
}

class SpecialState implements State<SpecialObservation> {
}


class SpecialDynamics implements Dynamics<SpecialObservation> {
   getObservationChance(State<SpecialObservation> state, SpecialObservation observation) {
       // state should be SpecialState, observation should be SpecialObservation!
   }
}

class Main<O extends Observation> {
  Main(State<O> state, O observation, Dynamics<O> dynamics) {
      dynamics.getObservationChance(state, observation);
   }
}

当然,只有当State接口的方法足够用于getObservationChance方法时,这种方法才有效。

更通用的方法是对所有三种类型进行参数化:

public interface Observation<O extends Observation<O, S, D>,
                             S extends State<O,S,D>,
                             D extends Dynamics<O,S,D>>
{
    ...
}

public interface State<O extends Observation<O,S,D>,
                       S extends State<O,S,D>,
                       D extends Dynamics<O,S,D>> {
}

public interface Dynamics<O extends Observation<O,S,D>,
                          S extends State<O,S,D>,
                          D extends Dynamics<O,S,D>> {
  getObservationChance(S state, O observation);
}

然后我们可以将实现定义为:

enum SpecialObservation implements Observation<SpecialObservation, SpecialState, SpecialDynamics> {
  FREE, WALL, etc.
}

class SpecialState implements State<SpecialObservation, SpecialState, SpecialDynamics> {
}


class SpecialDynamics implements Dynamics<SpecialObservation, SpecialState, SpecialDynamics> {
   getObservationChance(SpecialObservation state, SpecialObservation observation) {
       // state should be SpecialState, observation should be SpecialObservation!
   }
}

然后主类需要所有三个参数:

class Main<O extends Observation<O,S,D>,
           S extends State<O,S,D>,
           D extends Dynamics<O,S,D>> {
  Main(S state, O observation, D dynamics) {
      dynamics.getObservationChance(state, observation);
   }
}

在你的情况下,事实上动态只取决于观察和状态,而不是相反(并且这些不依赖于彼此),所以另一种方式是:

public interface Observation {
    ...
}

public interface State {
}

public interface Dynamics<S extends State,
                          O extends Observation> {
  getObservationChance(S state, O observation);
}

enum SpecialObservation implements Observation {
  FREE, WALL, etc.
}

class SpecialState implements State {
}


class SpecialDynamics implements Dynamics<SpecialState, SpecialObservation> {
   getObservationChance(SpecialState state, SpecialObservation observation) {
       // state should be SpecialState, observation should be SpecialObservation!
   }
}

class Main<S extends State, O extends Observation> {
  Main(S state, O observation, Dynamics<S, O> dynamics) {
      dynamics.getObservationChance(state, observation);
   }
}

编辑: 关于getAllObservations方法: 只要你能以某种方式使你的类型参数具体化,这里没有真正的问题。 要访问特定类型的枚举常量列表,您需要访问此类型 - 直接(SpecialObservation.values()),或者像这里的类对象:

class Main<S extends State, O extends Observation> {

  public O[] getAllObservations(Class<O> oClass) {
     return oClass.getEnumConstants();
  }

  Main(S state, Dynamics<S, O> dynamics, Class<O> observationClass) {
      O[] observations = getAllObservations(observationClass);
      for(O o : observations) {
         dynamics.getObservationChance(state, observation);
      }
   }
}

(当然,只有当O是枚举类时才有效。)

如果你有一个混合列表,它会变得更复杂,然后输入动态,动作,观察和状态类也不是很容易。

答案 1 :(得分:2)

您可以在枚举中添加方法:

enum SpecialObservation() implements Observation{
  FREE{
    void doSth(){
    }

    Collection<Observation> getPossibleObservations{
    }
  }, WALL, etc.
}

答案 2 :(得分:1)

使用界面:

interface Observation{  
  Collection<Observation>getSubObservations();
}

enum SpecialObservation implements Observation {
  FREE, 
  DOOR (FREE),
  WINDOW (FREE),
  WALL (DOOR, WINDOW, FREE);

  private Collection<Observation> subObservations;

  private SpecialObservation(Observation... subObservations) {
    this.subObservations = subObservations;
  }

  public Collection<Observation> getSubObservations() {
    return subObservations;
  }
}

答案 3 :(得分:0)

由于Java实现枚举的方式,不可能有抽象的枚举,并且通过正确的设计,您不需要使用枚举。但是,据我记忆,你可以在枚举中定义自己的方法...(你可能要检查一下......我已经有一段时间没有接触过Java了)