我有一个问题,使用开关情况的instanceof对象:

例如:我的问题可以在Java中重现:

if(this instanceof A)
    doA();
else if(this instanceof B)
    doB();
else if(this instanceof C)
    doC():

如何使用switch…case实现它?


当前回答

如果你绝对不能编码到接口,那么你可以使用枚举作为中介:

public A() {

    CLAZZ z = CLAZZ.valueOf(this.getClass().getSimpleName());
    switch (z) {
    case A:
        doA();
        break;
    case B:
        doB();
        break;
    case C:
        doC();
        break;
    }
}


enum CLAZZ {
    A,B,C;

}

其他回答

正如前面的回答所讨论的,传统的面向对象方法是使用多态性而不是开关。对于这种技巧,甚至有一个经过良好记录的重构模式:用多态性替换Conditional。每当我使用这种方法时,我也喜欢实现一个Null对象来提供默认行为。

从Java 8开始,我们可以使用lambda和泛型来提供函数式程序员非常熟悉的东西:模式匹配。它不是语言的核心特性,但是VAVR库(以前是Javaslang库)提供了一个实现。文档中的例子:

Match.ofType(Number.class)
    .caze((Integer i) -> i)
    .caze((String s) -> new BigDecimal(s))
    .orElse(() -> -1)
    .apply(1.0d); // result: -1

它不是Java世界中最自然的范例,所以要谨慎使用。虽然泛型方法将使您不必对匹配的值进行类型转换,但我们缺少一种分解匹配对象的标准方法,例如Scala的case类。

在最近发布的Java 19中,这非常简单和有用: 创建接口,并具有名为makesomenoise()的方法,它接受动物参数。

void makeSomeNoise (Animal animal) {
switch (animal) {
case Dog dog → dog.bark();
case Cat catcat.meow();
default throw new RuntimeException ("WTH is it???");
}
}

不,这是不可能的。然而,您可能想要做的是将多态性作为处理这类问题的一种方法。

创建一个带有类名的Enum。

public enum ClassNameEnum {
    A, B, C
}

找到对象的Class名称。 在枚举上写一个开关案例。

private void switchByClassType(Object obj) {

        ClassNameEnum className = ClassNameEnum.valueOf(obj.getClass().getSimpleName());

        switch (className) {
            case A:
                doA();
                break;
            case B:
                doB();
                break;
            case C:
                doC();
                break;
        }
    }
}

希望这能有所帮助。

这是子类型多态有助于实现的典型场景。执行以下步骤

interface I {
  void do();
}

class A implements I { void do() { doA() } ... }
class B implements I { void do() { doB() } ... }
class C implements I { void do() { doC() } ... }

然后您可以简单地在此上调用do()。

如果您不能自由地更改A、B和C,则可以应用访问者模式来实现相同的目的。