枚举抽象问题

发布于 2024-10-29 12:32:06 字数 778 浏览 6 评论 0原文

我目前正在努力解决 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 应该是可能观察的枚举(或类似的东西),但我想要问题的抽象表示。所以我想要一个观察,它应该包含观察一个返回所有可能观察列表的函数。最后一件事对于我正在实现的算法非常重要,因为我必须总结所有可能的观察结果。

谢谢!

I am currently struggling with a java abstraction problem. I have something like this:

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 should be an enum (or something like that) of possible observations, but I want to have an abstract representation of the problem. So I want an Observation that should contain the observation and a function that returns a list of all possible observations. The last thing is very important for an algorithm I am implementing, since I have to summarize over all possible observations.

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

孤者何惧 2024-11-05 12:32:06

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

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

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当然,它是一个枚举类。)

如果您有一个混合列表,它会变得更加复杂,并且类型安全地匹配 Dynamics、Action、Observation 和 State 类也不是那么容易。

You need parametrized types here - you have families of tree types each: a state, a observation, and a dynamics.

If we take the observation enum as the parameter type, we could convert your type to something like this:

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

This approach only works if the methods of our State interface are enough for the getObservationChance method, of course.

A more general approach would be to parametrize over all three types:

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

Then we can define the implementations as this:

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

The main class then needs all three parameters, of course:

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

In your case in fact the dynamics is only dependent on the observation and state, and not the other way around (and these are not dependent on each other), so another way would be this:

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

Edit:
About the getAllObservations method:
As long as you somehow can make your type parameters concrete, there is no real problem here.
To access the list of enum constants of a specific type, you need access to this type - either directly (SpecialObservation.values()), or with a class object like here:

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

(This only works if O is an enum class, of course.)

If you have a mixed list, it gets more complicated, and then it is also not really easy to type-safely match the Dynamics, Action, Observation and State classes.

救赎№ 2024-11-05 12:32:06

您可以向枚举添加方法:

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

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

You could add methods to your enums:

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

    Collection<Observation> getPossibleObservations{
    }
  }, WALL, etc.
}
蹲墙角沉默 2024-11-05 12:32:06

使用接口:

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

Use an interface:

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;
  }
}
最好是你 2024-11-05 12:32:06

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

Because of the way Java implements enums, it is not possible to have abstract enums, and with correct design you will not feeel the need for one. However, so far as I remember, you can define your own methods within enum...(you may have to check this..I've not been in touch with Java for some time now)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文