我有一个问题,使用开关情况的instanceof对象:
例如:我的问题可以在Java中重现:
if(this instanceof A)
doA();
else if(this instanceof B)
doB();
else if(this instanceof C)
doC():
如何使用switch…case实现它?
我有一个问题,使用开关情况的instanceof对象:
例如:我的问题可以在Java中重现:
if(this instanceof A)
doA();
else if(this instanceof B)
doB();
else if(this instanceof C)
doC():
如何使用switch…case实现它?
当前回答
不,这是不可能的。然而,您可能想要做的是将多态性作为处理这类问题的一种方法。
其他回答
正如前面的回答所讨论的,传统的面向对象方法是使用多态性而不是开关。对于这种技巧,甚至有一个经过良好记录的重构模式:用多态性替换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类。
Eclipse建模框架有一个有趣的想法,它也考虑了继承。Switch接口中定义了基本概念:通过调用doSwitch方法来完成切换。
真正有趣的是实现。对于每种类型的兴趣,a
public T caseXXXX(XXXX object);
方法必须实现(默认实现返回null)。doSwitch实现将尝试为对象的所有类型层次结构调用所有caseXXX方法。之类的东西:
BaseType baseType = (BaseType)object;
T result = caseBaseType(eAttribute);
if (result == null) result = caseSuperType1(baseType);
if (result == null) result = caseSuperType2(baseType);
if (result == null) result = caseSuperType3(baseType);
if (result == null) result = caseSuperType4(baseType);
if (result == null) result = defaultCase(object);
return result;
实际框架为每个类使用一个整数id,所以逻辑实际上是一个纯切换:
public T doSwitch(Object object) {
return doSwitch(object.class(), eObject);
}
protected T doSwitch(Class clazz, Object object) {
return doSwitch(getClassifierID(clazz), object);
}
protected T doSwitch(int classifierID, Object theObject) {
switch (classifierID) {
case MyClasses.BASETYPE:
{
BaseType baseType = (BaseType)object;
...
return result;
}
case MyClasses.TYPE1:
{
...
}
...
您可以查看ECoreSwitch的完整实现,以获得更好的理解。
你不能只使用字节,short, char, int, String和枚举类型(以及原语的对象版本,这也取决于你的java版本,字符串可以在java 7中切换)
下面是在Java 8中使用http://www.vavr.io/来实现这一功能的方法
import static io.vavr.API.*;
import static io.vavr.Predicates.instanceOf;
public Throwable liftRootCause(final Throwable throwable) {
return Match(throwable).of(
Case($(instanceOf(CompletionException.class)), Throwable::getCause),
Case($(instanceOf(ExecutionException.class)), Throwable::getCause),
Case($(), th -> th)
);
}
在最近发布的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???");
}
}