1

実装は同じですが、名前が異なる 2 つのクラスがあります。それらは生成され、私はそれらを変更することができません:

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 の Adapter パターンを実装している最中ですが、私の最終ステップは彼のものとは異なります。インターフェイス オブジェクトの条件付き割り当てが必要です。以下は私が持っているもので、これまでのところエラーや警告はありませんが、何らかの理由でこれが良い習慣ではないのでしょうか? おそらく、リフレクションまたはジェネリックを使用して、インターフェイスのクラスを決定する必要がありますか? これは、私のコードだけが呼び出すメソッドになり、条件がわかります。条件付きインターフェイスの割り当てを検索しましたが、あまり見つかりませんでした。

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 では、 と を変更できないと仮定するFooと、 AdapterパターンBarが必要になります。最初にとの抽象化を作成します。FooBar

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

そして、これらのような2つのアダプターがあります(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

タグ付きクラスを作成できます。

クラス階層を使用するよりも劣っているため、これはアンチパターンと見なされますが、階層を制御できないため、選択の余地はほとんどありません。

これにより、に頼ることなく、Web サービスを介して何を送信するかを知ることができます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

おそらく、生成されたクラスを制御することはできません (そうでなければ、簡単なことです!)。

別の方法として、ヘルパー クラスを作成し、リフレクションを使用して、設定する必要のあるすべてのプロパティを設定することもできます (メソッド名が文字列として指定されたときに Java メソッドを呼び出すにはどうすればよいですか? を参照してください) 。

于 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;
    }
}

必要に応じて検証を追加して、1 つのラッパーが 1 つのアイテムのみを参照するようにすることができます。

于 2012-07-25T17:55:53.670 に答える