答案 0 :(得分:5)
EMF为您的元模型生成了一个从org.eclipse.emf.ecore.util.Switch<T>
派生的实用程序类,允许您在考虑继承关系的情况下根据对象的实际类型“轻松”访问您的EMF模型。
实际上,生成的实用工具类中的Javadoc声明了
模型的继承层次结构的开关。它支持调用doSwitch(object)来为模型的每个类调用caseXXX方法,从对象的实际类开始,继续进行继承层次结构,直到返回非空结果,这是切换的结果
这样,您不必自己手动实现 Visitor 类,并且可以依赖于这样生成的实用程序类。生成的switch类也是通用类,因此您可以将其用于计算任何类型的值。
这个想法是,您将创建一个生成的开关类的子类,并仅覆盖要处理的模型元素的caseXXX方法。然后,创建此类子类的实例,并调用doSwitch
传递模型的实例。
对于元模型中的每种XXX类型,您都有一个caseXXX方法。默认情况下,也就是没有其他大小写方法匹配时,您还有一个defaultCase()
方法。
例如,如果您在元模型中具有类型A
,B1
和B2
,则在生成的开关类中具有方法caseA
,{{1} }和caseB1
,您可以重新定义。请记住,默认实现只是返回caseB2
。如果null
和B1
是B2
的子类型,而您仅重新定义了A
和caseA
,则如果您通过{{1 }},则将使用方法caseB1
。如果您调用doSwitch
并传递B1
,则将使用方法caseB1
:实际上,没有doSwitch
,但是B2
是{{1 }}。
例如,对于Ecore模型本身,您有caseA
。这个例子以JUnit测试的形式进行,其中创建了caseB2
的子类来访问Ecore模型(它只是返回带有一些信息的字符串,请注意,它还会访问子级):
B1
如您所见,A
捕获了org.eclipse.emf.ecore.util.EcoreSwitch
,因为没有EcoreSwitch
,但是捕获了public class EcoreSwitchTest {
private static EcoreFactory factory = EcoreFactory.eINSTANCE;
@Test public void exampleEcoreSwitch() {
// given
EAttribute eAttribute = factory.createEAttribute();
EReference eReference = factory.createEReference();
EClass eClass = factory.createEClass();
eClass.getEStructuralFeatures().add(eAttribute);
eClass.getEStructuralFeatures().add(eReference);
EDataType eDataType = factory.createEDataType();
EPackage ePackage = factory.createEPackage();
ePackage.getEClassifiers().add(eClass);
ePackage.getEClassifiers().add(eDataType);
EcoreSwitch<String> mySwitch = new EcoreSwitch<String>() {
@Override
public String caseEClass(EClass c) {
return "EClass\n" +
c.getEStructuralFeatures().stream()
.map(this::doSwitch)
.collect(Collectors.joining());
};
@Override
public String caseEAttribute(EAttribute a) {
return " EAttribute\n";
};
@Override
public String caseEStructuralFeature(EStructuralFeature f) {
return " EStructuralFeature("
+ f.eClass().getName() + ")\n";
};
@Override
public String defaultCase(EObject o) {
return "Unknown\n";
};
};
// when
String result = ePackage.getEClassifiers().stream()
.map(o -> mySwitch.doSwitch(o))
.collect(Collectors.joining());
// then
assertEquals(
"EClass\n" + // caseEClass
" EAttribute\n" + // caseEAttribute
" EStructuralFeature(EReference)\n" + // caseEStructuralFeature
"Unknown\n" + // defaultCase
"", result);
}
}
,因为有更具体的caseEStructuralFeature
。
同样,通过从EMF为您的元模型生成的Switch类派生,您可以轻松地访问模型。
答案 1 :(得分:2)
switch类是一个允许您根据模型对象(在本例中为EMF模型对象)选择和实例化类型的具体实例的类。我见过的例子表明它对于为EMF模型实例化特定类型的适配器很有用。
您可以通过覆盖doSwitch方法来使用它。例如,假设我有一个模型对象,我想实例化一个与我模型中type
值对应的适配器对象:
public class ExampleSwitch extends Switch<Adapter> {
public Adapter doSwitch(EObject eobject) {
if (eobject instanceof MyModel) {
switch (eobject.getType()) {
case TYPEA:
Adapter result = createTypeAAdapter(eobject);
if (result == null) {
return createDefaultAdapter(eobject);
}
return result;
case TYPEB:
...
default:
}
}
}
}
eclipse org.eclipse.emf.common.notify.AdapterFactory将使用它来返回一个适配器。
public class MyAdapterFactory implements AdapterFactory {
public boolean isFactoryForType(Object o) {
return (o instanceof MyModel);
}
public Adapter adapt(Notifier notifier, Object type) {
return mySwitch.doSwitch((EObject)notifier);
}
}
我已从here提取此信息。我还没有对此进行验证,但显然EMF生成器可以选择为您生成AdapterFactories和Switch类。
答案 2 :(得分:-2)
Java中的所有内容都是类。 (除了原语)。因此,当您使用switch
时,在幕后调用具有switch
所有逻辑的类。 Switch<T>
可能是其他开关类在您使用它们时继承和实现方法的类。例如,您可以使用switch(int)
,也可以使用switch(String)
,两种功能都不同,必须在某处定义。