【问题标题】:Elegant way of returning opposite enum [duplicate]返回相反枚举的优雅方式[重复]
【发布时间】:2020-08-02 01:21:27
【问题描述】:

我有一个枚举,每个元素都有一个相反的元素。我想要一种优雅的方式将它封装在枚举的每个元素中。我的首选选项不合法,因为它使用前向引用。

enum Direction {
    NORTH(SOUTH), SOUTH(NORTH), EAST(WEST), WEST(EAST);

    private final Direction opposite;

    Direction(Direction opposite) {
        this.opposite = opposite;
    }

    public Direction getOpposite() {
        return opposite;
    }
}

使用供应商也是违法的。

enum Direction {
    NORTH(() -> SOUTH), SOUTH(() -> NORTH), EAST(() -> WEST), WEST(() -> EAST);

    private final Supplier<Direction> opposite;

    Direction(Supplier<Direction> opposite) {
        this.opposite = opposite;
    }

    public Direction getOpposite() {
        return opposite.get();
    }
}

这让我不得不重写该方法:

enum Direction {
    NORTH{
        public Direction getOpposite() {
            return SOUTH;
        }
    }, 
    SOUTH{
        public Direction getOpposite() {
            return NORTH;
        }
    }, 
    EAST{
        public Direction getOpposite() {
            return WEST;
        }
    }, 
    WEST{
        public Direction getOpposite() {
            return EAST;
        }
    };

    public abstract Direction getOpposite();
}

使用开关:

enum Direction {
    NORTH, SOUTH, EAST, WEST;

    public Direction getOpposite() {
        return switch(this) {
            case NORTH -> SOUTH;
            case SOUTH -> NORTH;
            case EAST -> WEST;
            case WEST -> EAST;
        }
    }
}

或者地图:

enum Direction {
    NORTH, SOUTH, EAST, WEST;

    private static final Map<Direction,Direction> OPPOSITES =
        Map.of(NORTH, SOUTH, SOUTH, NORTH, EAST, WEST, WEST, EAST);

    public Direction getOpposite() {
        OPPOSITES.get(this);
    }
}

没有任何一种选择比仅仅将相反的情况作为一个论点列出来那么简单或易读。

有没有避免前向引用问题的优雅方法?

【问题讨论】:

  • 为什么不在if..else中使用multiole或语句??
  • 另一种选择是使用static{..} 初始化块在枚举值已经存在之后设置它们,就像在stackoverflow.com/a/18883717中一样
  • 地图选项还不错。查找时间也很棒。这个问题有点武断和主观,因为标准是elegant,不管这意味着什么。
  • 我个人会使用 Map 并提供类似 public static Direction#inverse(Direction) 的函数,并使用私有静态最终 Map 并使用 guava ImmutableMap 作为 Map 实现。
  • switch 语句相对于映射的优势在于,如果您稍后添加另一个枚举值,编译器会告诉您是否忘记更新案例。地图不会发生这种情况。

标签: java enums


【解决方案1】:

我建议你改变顺序:

enum Direction {
    NORTH, EAST, WEST, SOUTH:
    ...
}

并使用Direction.values()

public Direction opposite() {
    Direction[] array = values();

    return array[(ordinal() + 2) % array.length];
}

【讨论】:

  • 聪明的选择,但为什么超过values()
  • 我更喜欢values()——只是扫描javadoc太快了。相应地改变了我的答案。
  • 依赖枚举中的顺序似乎...脆弱? TBH 我更喜欢 Map 方法。
  • 我不确定我是否不同意,但开发人员需要在盲目添加另一个成员之前检查任何实现实例方法的 Enum
【解决方案2】:

不知道会不会好一点:

enum Direction {
    NORTH("SOUTH"), SOUTH("NORTH"), EAST("WEST"), WEST("EAST");

    private final String opposite;

    Direction(String opposite) {
        this.opposite = opposite;
    }

    public Direction getOpposite() {
        return Direction.valueOf(opposite);
    }
}

【讨论】:

    猜你喜欢
    • 2013-09-23
    • 2012-11-04
    • 2014-07-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多