【问题标题】:Utilizing switch statements with enums and marker interface使用带有枚举和标记接口的 switch 语句
【发布时间】:2021-12-22 18:40:46
【问题描述】:

我有一个标记界面

public interface Marker{}

和两个实现标记的枚举

public enum Sharpie implements Marker{
    RED,
    BLUE,
    BLACK
}

public enum Crayola implements Marker{
    PURPLE,
    ORANGE,
    GREEN
}

我正在尝试做的是利用 switch 语句,例如

public boolean isOwned(Marker m){
    // Take in a marker of either Sharpie, or Crayola
    switch(m){
        case BLUE:
        case BLACK:
        case GREEN:
            return true;
        default:
            return false;
    }
}

有没有办法在不使用昂贵的instanceof 电话的情况下做到这一点?

这样的东西会起作用,但我尽量避免使用instanceof,坦率地说,它看起来有点难看。

public boolean isOwned(Marker m){

    // First determine instanceof and then cast the marker 
    // to the appropriate Type before utilizing the switch statement
    if (m instanceof Sharpie){
       switch((Sharpie) m){
           Case BLUE:
           Case BLACK:
               return true;
           default:
               return false;
       }
    } else {
       switch((Crayola) m){
           case Green:
               return true;
           default:
               return false;
       }
    }
}

【问题讨论】:

  • 也许不要让你的界面成为一个标记。使其公开一个isOwned() API 方法,该方法将由您的枚举实现。这样一来,您就可以完全摆脱 switch
  • 不幸的是,这个想法是不同的标记将由不同的“人”拥有。该信息将由个人“人”确定。也许,更好的名称是doesOwn(),因为不同的实例将拥有不同的标记。让枚举实现这个方法是不允许的。
  • 不过,您可以使用Marker 使枚举在所有实现中公开唯一值。例如,如果每个枚举都可以公开一个String getUniqueColor() 方法,那么您的外部isOwned() 方法甚至可以使用switch,而无需依赖于Marker 参数的运行时类型。
  • @user16320675 的建议也是我所期望的实现方式:让每个人都拥有一个Set<Marker>,然后使用contains()。或者,要实现您当前拥有的逻辑,您可以使用静态 Map<Marker, Boolean> 并使用它来查找返回值。

标签: java enums switch-statement


【解决方案1】:

看起来是尝试新 Java 功能 Sealed InterfacePattern Matching for switch Expressions(* 这是 jdk 17 的预览功能)的好场景

首先将Marker设为密封接口

public sealed interface Marker permits Crayola, Sharpie {}

然后我们可以使用switch表达式来摆脱那些instanceof的检查。

    public boolean isOwned(Marker marker) {
        boolean isOwned = switch (marker) {
            case Sharpie s -> s == Sharpie.BLACK || s == Sharpie.BLUE;
            case Crayola c -> c == Crayola.GREEN;
        };
        return isOwned;
    }

【讨论】:

  • 有趣。谢谢。
  • 很高兴知道!我会接受这个答案。但是,由于我仅限于 Java 8,因此我实际上采用了其他 cmets 建议的 Set 方法。
  • @user15708369 仅供参考,还有一个 EnumSet(如果尚未使用)
【解决方案2】:

只需将switch 更改为if。不需要instanceof

public boolean isOwned(Marker m){
    if(m == Sharpie.BLUE || m == Sharpie.BLACK || m == Crayola.GREEN)
        return true;
    return false;
}

【讨论】:

    【解决方案3】:

    我不知道你在做什么。此示例对 2 个不同的枚举使用唯一函数。我认为你应该在枚举 like this 中使用扩展。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-12-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多