【问题标题】:Avoiding instanceof when polymorphism can't be used在不能使用多态性时避免使用 instanceof
【发布时间】:2016-03-10 22:16:34
【问题描述】:

我有多个使用XJCXSD 文件生成的类。这些类是作为构建过程的一部分自动生成的,因此无法修改。这些类共享一个共同的结构。我有需要使用这些类的客户端代码。但是,某些客户端逻辑对于所有类都是相同的。因此,我不想为每个要支持的类复制客户端代码。在这种情况下想到的流行解决方案是使用接口/继承,以便客户端代码只处理超类/接口而不是特定类。但是,在这种情况下,这种解决方案是不可能的,因为无法修改类。因此,我想正确的方向是使用组合而不是继承。但是,如果使用组合,组合类将需要处理每个特定的类,所以我最终可能会使用许多 if (obj instanceof Type) 来分别处理每个案例。

public class A {
    private int id;
    //Properties specific to type A
}

public class B {
    private int id;
    //Properties specific to type B
}

public class C {
    private int id;
    //Properties specific to type C
}

public class Client {
    public void myMethod(Object obj) {
        //obj may be an instance of A, B or C

        //I would like to access the id property (which is common to A, B and C)
        //using the most elegant way

        //Approach using instanceof
        if(obj instanceof A) {
            A objA = (A)obj;
            objA.getId();
        }
        if(obj instanceof B) {
            B objB = (B)obj;
            objB.getId();
        }
        if(obj instanceof C) {
            C objC = (C)obj;
            objC.getId();
        }
    }
}

我考虑过使用包装实例的方法,并且 instanceof 逻辑在包装类内部而不是客户端代码中。

public class Wrapper {
    private Object obj;

    public int getId() {
        if(obj instanceof A)
            return ((A)obj).getId();
        if(obj instanceof B)
            return ((B)obj).getId();
        if(obj instanceof C)
            return ((C)obj).getId();
    }
}

public class Client {
    public void myMethod(Wrapper wrapper) {
        //Only deals with wrappers, not with the objects themselves

        wrapper.getId();
    }
}

在这种情况下是否需要使用instanceof?如果是,推荐的方法是什么?


编辑:

反射也可以用来避免多个instanceof。按照给定的示例,如果在每个类(ABC)中都定义了 getId() 方法,则可能出现以下情况:

public class Wrapper {
    private Object obj;

    public int getId() {
        return obj.getClass().getMethod("getId").invoke(obj);
    }
}

我忘了提到我对 XSD 没有任何控制权。

【问题讨论】:

  • 您可以使用xjb文件来自定义类的生成,并让它们实现一个接口。例如,请参阅stackoverflow.com/questions/2916217/…
  • @JBNizet 根据我的经验,尝试调整 JAXB/XJC 可能是一场噩梦。此外,实现接口需要在生成的类中覆盖方法,但情况可能并非总是如此。相似的结构并不一定意味着相同的方法。可能存在名称不同但返回信息在逻辑上等效的方法。
  • 每个班级都有getId() 方法吗?如果是,您知道使用反射的解决方案。
  • 好吧,如果所有应该有 getId() 方法的类都没有 getId() 方法,那么这表明你的架构有问题,因为你希望它们有一个。并且编译器会警告您该问题(调用 getId() 的基于反射的方法不会出现这种情况)。您可以选择哪些类实现了哪个接口。 XJB 允许这样做。我并不是说您的所有类都实现了该接口。只有应该实现它的类,因为它们都应该有一个返回 int 的 getId() 方法。
  • @JBNizet 是的,但就我而言,我无法控制架构。

标签: inheritance design-patterns polymorphism object-composition


【解决方案1】:

您可以使用impromptu-interface

C# 4.0 (.net & silverlight) 框架允许您包装任何对象 (静态或动态)具有静态接口,即使它没有 继承它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-04-18
    • 2022-11-15
    • 2011-09-03
    • 2013-03-05
    • 2012-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多