【问题标题】:Enum RPS-implementation gives self-reference in initializer and illegal forward reference枚举 RPS 实现在初始化器中提供自引用和非法前向引用
【发布时间】:2014-03-19 08:41:32
【问题描述】:

我有以下代码,我相信我明白了为什么我得到了错误:

错误是,例如:

  • 初始化器中的自引用ROCKRPSGesture.ROCK的构造函数中。
  • 非法前向引用ROCKRPSGesture.PAPER的构造函数中。

public interface Gesture {
    public List<? extends Gesture> winsFrom();

    public List<? extends Gesture> tiesTo();

    public List<? extends Gesture> losesTo();
}

public enum RPSGesture implements Gesture, Action {
    ROCK(
        Arrays.asList(RPSGesture.SCISSORS),
        Arrays.asList(RPSGesture.ROCK),
        Arrays.asList(RPSGesture.PAPER)
    ),

    PAPER(
        Arrays.asList(RPSGesture.ROCK),
        Arrays.asList(RPSGesture.PAPER),
        Arrays.asList(RPSGesture.SCISSORS)
    ),

    SCISSORS(
        Arrays.asList(RPSGesture.PAPER),
        Arrays.asList(RPSGesture.SCISSORS),
        Arrays.asList(RPSGesture.ROCK)
    );

    private final List<RPSGesture> winsFrom;
    private final List<RPSGesture> tiesTo;
    private final List<RPSGesture> losesTo;

    private RPSGesture(final List<RPSGesture> winsFrom, final List<RPSGesture> tiesTo, final List<RPSGesture> losesTo) {
        this.winsFrom = winsFrom;
        this.tiesTo = tiesTo;
        this.losesTo = losesTo;
    }

    @Override
    public List<RPSGesture> winsFrom() {
        return winsFrom;
    }

    @Override
    public List<RPSGesture> tiesTo() {
        return tiesTo;
    }

    @Override
    public List<RPSGesture> losesTo() {
        return losesTo;
    }
}

我见过Peter Lawrey's Answer,但是static 初始化器真的是最好的方法吗?还有其他合理的选择吗?

这个枚举的设计看起来是否正确,或者你自己会做不同的事情吗?希望类中的代码更少。

【问题讨论】:

  • 好吧,你总是tiesTo()自己,不是吗?只需让tiesTo() 返回Collections.&lt;Gesture&gt;singletonList(this)...
  • @fge 我不太确定。在常规的 Rock-Paper-Scissors 中是的,但是在自定义变体中,您可能能够绑定多个手势。
  • 要么是 static 初始化器(在 enum 的情况下,这与构造函数相同)或者只是实现方法 in enum 实例。

标签: java enums


【解决方案1】:

我自己找到了一种合适的方法,使用 Java 8:

public interface Gesture {
    public List<? extends Gesture> winsFrom();

    public List<? extends Gesture> tiesTo();

    public List<? extends Gesture> losesTo();
}

public enum RPSGesture implements Gesture, Action, RuleGestureFPSFactory {
    ROCK,
    PAPER,
    SCISSORS;

    @Override
    public List<RPSGesture> winsFrom() {
        return winMapping().get(this);
    }

    @Override
    public List<RPSGesture> tiesTo() {
        return tieMapping().get(this);
    }

    @Override
    public List<RPSGesture> losesTo() {
        return loseMapping().get(this);
    }
}

public interface RuleGestureFactory<T extends Gesture> {
    public Map<T, List<T>> winMapping();

    public Map<T, List<T>> tieMapping();

    public Map<T, List<T>> loseMapping();
}

public interface RuleGestureFPSFactory extends RuleGestureFactory<RPSGesture> {
    @Override
    default public Map<RPSGesture, List<RPSGesture>> winMapping() {
        Map<RPSGesture, List<RPSGesture>> mapping = new HashMap<>();
        mapping.put(ROCK, Arrays.asList(SCISSORS));
        mapping.put(PAPER, Arrays.asList(ROCK));
        mapping.put(SCISSORS, Arrays.asList(PAPER));
        return mapping;
    }

    @Override
    default public Map<RPSGesture, List<RPSGesture>> tieMapping() {
        Map<RPSGesture, List<RPSGesture>> mapping = new HashMap<>();
        mapping.put(ROCK, Arrays.asList(ROCK));
        mapping.put(PAPER, Arrays.asList(PAPER));
        mapping.put(SCISSORS, Arrays.asList(SCISSORS));
        return mapping;
    }

    @Override
    default public Map<RPSGesture, List<RPSGesture>> loseMapping() {
        Map<RPSGesture, List<RPSGesture>> mapping = new HashMap<>();
        mapping.put(ROCK, Arrays.asList(PAPER));
        mapping.put(PAPER, Arrays.asList(SCISSORS));
        mapping.put(SCISSORS, Arrays.asList(ROCK));
        return mapping;
    }
}

这样你甚至可以很容易地拥有不同的规则实现,但是它不支持在运行时切换。

【讨论】:

  • 我也会考虑使用 List 的 EnumSet 作为映射映射中的值。
猜你喜欢
  • 2011-08-06
  • 2015-09-18
  • 2011-12-31
  • 1970-01-01
  • 2023-03-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多