我有一个问题,使用开关情况的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实现它?
当前回答
这是子类型多态有助于实现的典型场景。执行以下步骤
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,则可以应用访问者模式来实现相同的目的。
其他回答
我知道这有点晚了,但对于未来的读者来说……
注意上面的方法,这些方法仅仅是基于A, B, C类的名称…:
除非你能保证A, B, C…(Base的所有子类或实现者)是final,然后A, B, C的子类…不会被处理。
即使if, elseif, elseif ..方法对于大量子类/实现者较慢,它更准确。
我认为使用switch语句是有原因的。如果你使用xText生成的代码。或者另一种EMF生成的类。
instance.getClass().getName();
返回类实现名称的字符串。即: org.eclipse.emf.ecore.util.EcoreUtil
instance.getClass().getSimpleName();
返回简单的表示形式,即: EcoreUtil
创建一个Map,其中键为Class<?>,值为表达式(lambda或类似)。考虑:
Map<Class,Runnable> doByClass = new HashMap<>();
doByClass.put(Foo.class, () -> doAClosure(this));
doByClass.put(Bar.class, this::doBMethod);
doByClass.put(Baz.class, new MyCRunnable());
// of course, refactor this to only initialize once
doByClass.get(getClass()).run();
如果你需要检查异常,那就实现一个抛出异常的FunctionalInterface,而不是使用Runnable。
下面是一个真实的单词前后对比,展示了这种方法如何简化代码。
重构映射之前的代码:
private Object unmarshall(
final Property<?> property, final Object configValue ) {
final Object result;
final String value = configValue.toString();
if( property instanceof SimpleDoubleProperty ) {
result = Double.parseDouble( value );
}
else if( property instanceof SimpleFloatProperty ) {
result = Float.parseFloat( value );
}
else if( property instanceof SimpleBooleanProperty ) {
result = Boolean.parseBoolean( value );
}
else if( property instanceof SimpleFileProperty ) {
result = new File( value );
}
else {
result = value;
}
return result;
}
重构为映射后的代码:
private final Map<Class<?>, Function<String, Object>> UNMARSHALL =
Map.of(
SimpleBooleanProperty.class, Boolean::parseBoolean,
SimpleDoubleProperty.class, Double::parseDouble,
SimpleFloatProperty.class, Float::parseFloat,
SimpleFileProperty.class, File::new
);
private Object unmarshall(
final Property<?> property, final Object configValue ) {
return UNMARSHALL
.getOrDefault( property.getClass(), ( v ) -> v )
.apply( configValue.toString() );
}
这避免了重复,消除了几乎所有的分支语句,并简化了维护。
我个人比较喜欢下面的Java 1.8代码:
mySwitch("YY")
.myCase("AA", (o) -> {
System.out.println(o+"aa");
})
.myCase("BB", (o) -> {
System.out.println(o+"bb");
})
.myCase("YY", (o) -> {
System.out.println(o+"yy");
})
.myCase("ZZ", (o) -> {
System.out.println(o+"zz");
});
将输出:
YYyy
示例代码使用字符串,但您可以使用任何对象类型,包括Class。例如:. mycase (this.getClass(), (o) ->…
需要以下片段:
public Case mySwitch(Object reference) {
return new Case(reference);
}
public class Case {
private Object reference;
public Case(Object reference) {
this.reference = reference;
}
public Case myCase(Object b, OnMatchDo task) {
if (reference.equals(b)) {
task.task(reference);
}
return this;
}
}
public interface OnMatchDo {
public void task(Object o);
}
不,这是不可能的。然而,您可能想要做的是将多态性作为处理这类问题的一种方法。