1

我有两个具有相同实现但名称不同的类。它们是生成的,我无法修改它们:

public class Foo {

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

public class Bar {

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

我需要用数据填充这些类,并且由于它们是相同的,因此更愿意使用单个类或引用来完成,然后根据需要强制转换为(或希望解决方案更优雅)Foo 或 Bar。从概念上讲:

FooOrBar fob = ????;   
fob.setName("XYZ");

Foo f = fob.(???);
Bar b = fob.(???);

我已经研究过泛型,但它似乎是为了当你真的不知道你将在哪个类上运行时。我是否有可能拥有某种类型的类或参考来实现这一目标?

7月26日编辑:

抱歉,如果这样的跟进形式不好,我可以在需要时发布新的。我正在实施 Tomasz 的适配器模式,但我的最后一步与他的不同。我需要接口对象的条件分配。以下是我所拥有的,到目前为止我没有收到任何错误或警告,但我想知道这是否出于某种原因不是好的做法?也许我应该使用反射或泛型来确定接口的类?这将是一个只有我的代码会调用并且我会知道条件的方法。我搜索了条件接口分配,但没有找到太多。

FooOrBar fob;  //interface

if (condition true) {

    fob = new FooAdapter();  //FooAdapter implements FooOrBar
} else {
    fob = new BarAdapter();  //BarAdapter implements FooOrBar
}

fob.setName("XYZ");
4

4 回答 4

2

您要查找的内容称为,Java 不支持。尝试像这样的动态语言。

在 Java 中,假设您不能修改Fooand Bar,您将需要一个适配器模式。Foo首先在and上创建一个抽象Bar

public interface FooOrBar {
    String getName();
    void setName(String name);
}

并有两个这样的适配器(BarAdapter几乎相同):

public class FooAdapter implements FooOrBar {

    private final Foo foo;

    public FooAdapter(Foo foo) {
        this.foo = foo;
    }

    public String getName() {
        return foo.getName();
    }

    public void setName(String name) {
        foo.setName(name);
    }

}

现在你可以说:

FooOrBar fob = new FooAdapter(foo);
FooOrBar fob2 = new BarAdapter(bar);

fob.setName("XYZ");

我将把实际价值留给你(你真的需要它吗?)

于 2012-07-25T17:52:53.540 回答
1

您可以创建一个标记类。

这被认为是一种反模式,因为它们不如使用类层次结构,但是由于您无法控制层次结构,因此您别无选择。

这使您无需借助instanceof.

class FooBar {
    public static enum Mode { FOO, BAR }
    Foo foo;
    Bar bar;
    Mode mode;
    FooBar(Foo foo) {
        mode = Mode.FOO;
        this.foo = foo;
    }
    FooBar(Bar bar) {
        mode = Mode.BAR;
        this.bar = bar;
    }

    public String getName() {
        switch(mode) {
            case FOO: foo.getName();
            case BAR: bar.getName();
            default: throw new IllegalStateException();
        }
    }

    public void setName(String name) {
        switch(mode) {
            case FOO: foo.setName(name); return;
            case BAR: bar.setName(name); return;
            default: throw new IllegalStateException();
        }
    }
    public Mode getMode() { return mode; }
}
于 2012-07-25T17:57:26.433 回答
1

大概您无法控制生成的类(否则,这将是微不足道的!)。

另一种方法是创建一个辅助类并使用反射来设置您需要设置的每个属性(请参阅How do I invoke a Java method when given the method name as a string?

于 2012-07-25T17:58:55.217 回答
0

我不确定您的要求是什么,但您是否考虑过创建包含 foo 和 bar 实例的包装类的最简单解决方案?

class FooOrBar {
    private Foo foo;
    private Bar bar;

    public setName(name) {
        if (foo != null) foo.name = name;
        if (bar != null) bar.name = name;
    }
}

您可以根据需要添加验证,以确保单个包装器仅引用一个项目。

于 2012-07-25T17:55:53.670 回答