Switch类用于什么?

时间:2015-11-14 06:00:57

标签: java eclipse emf

什么是用于?

的开关类(派生自org.eclipse.emf.ecore.util.Switch<T>

javadoc将其解释为

  

所有切换类的抽象基类。

这没有用,因为我之前从未听说过“切换类”。

3 个答案:

答案 0 :(得分:5)

EMF为您的元模型生成了一个从org.eclipse.emf.ecore.util.Switch<T>派生的实用程序类,允许您在考虑继承关系的情况下根据对象的实际类型“轻松”访问您的EMF模型。

实际上,生成的实用工具类中的Javadoc声明了

模型的继承层次结构的开关。它支持调用doSwitch(object)来为模型的每个类调用caseXXX方法,从对象的实际类开始,继续进行继承层次结构,直到返回非空结果,这是切换的结果

这样,您不必自己手动实现 Visitor 类,并且可以依赖于这样生成的实用程序类。生成的switch类也是通用类,因此您可以将其用于计算任何类型的值。

这个想法是,您将创建一个生成的开关类的子类,并仅覆盖要处理的模型元素的caseXXX方法。然后,创建此类子类的实例,并调用doSwitch传递模型的实例。

对于元模型中的每种XXX类型,您都有一个caseXXX方法。默认情况下,也就是没有其他大小写方法匹配时,您还有一个defaultCase()方法。

例如,如果您在元模型中具有类型AB1B2,则在生成的开关类中具有方法caseA,{{1} }和caseB1,您可以重新定义。请记住,默认实现只是返回caseB2。如果nullB1B2的子类型,而您仅重新定义了AcaseA,则如果您通过{{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),两种功能都不同,必须在某处定义。