利用枚举和标记接口实现switch语句

4

我有一个标记接口

public interface Marker{}

还有两个实现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;
       }
    }
}

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

4
看起来是尝试新的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;
    }

有趣。谢谢。 - c0der
太好了,我会接受这个答案。不过,由于其他评论建议我只能使用Java 8,所以我实际上采用了Set<>方法。 - user15708369
1
@user15708369 提醒一下,如果你还没有使用过的话,这里也有一个 EnumSet - user16320675

1
只需将 switch 更改为 if,无需使用 instanceof
public boolean isOwned(Marker m){
    if(m == Sharpie.BLUE || m == Sharpie.BLACK || m == Crayola.GREEN)
        return true;
    return false;
}

0

我不知道你在做什么。这个例子使用了两个不同枚举的唯一函数。我认为你应该在枚举中使用扩展 像这样


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接