6

私の Java プロジェクトには、さまざまなタイプのトレーダーのベクトルがあります。これらの異なるタイプのトレーダーは、Trader クラスのサブクラスです。現在、Trader を引数として取り、それをベクトルに 50 回程度格納するメソッドがあります。同じオブジェクトを 50 回保存すると、同じオブジェクトの参照が50 回保存されるだけなので、問題が発生しています。オブジェクトのコピーを50 個保存する必要があります。Cloneの実装について調査しましたが、 Trader の型を定義するプログラマーがクラスを複製可能にすることについて心配する必要はありません。また、このページで指摘されているように、クローンを実装すると、あらゆる種類の問題が発生します。コピー コンストラクターも動作しないと思います。なぜなら、Trader クラスで定義した場合、コピーしている Trader の型がわからず、汎用の Trader を作成するだけだからです。私に何ができる?

編集:特定のオブジェクトの正確なコピーを作成したくありません。私が実際にやろうとしているのは、特定の数のトレーダーをベクターに追加することです。問題は、ユーザーが追加したいトレーダーのタイプを引数で指定する必要があることです。これが私がやろうとしていることの例です:(私の構文は完全に想像上のものですが)

public void addTraders(*traderType*)
{
    tradervect.add(new *traderType*())
}

Javaでこのようなことを達成するにはどうすればよいですか?

4

5 に答える 5

2

抽象コピー メソッドを追加するだけです。共変の戻り値の型を使用して、派生型が派生インスタンスを返すように指定できますが、これは重要である場合とそうでない場合があります。

public interface Trader {
    Trader copyTrader();
    ...
}


public final class MyTrader implements Trader {
    MyTrader copyTrader() {
        return new MyTrader(this);
    }
    ...
}

Trader場合によっては、クローンを作成してから適切に型指定されたコレクションを返す必要がある派生型のコレクションを一般的に処理したい場合があります。そのために、慣用的な方法でジェネリックを使用できます。

public interface Trader<THIS extends Trader> {
    THIS copyTrader();
    ...
}


public final class MyTrader implements Trader<MyTrader> {
    public MyTrader copyTrader() {
        return new MyTrader(this);
    }
    ...
}
于 2009-04-26T23:27:15.827 に答える
2

元のトレーダーが後のトレーダーのプロトタイプ (パターンを参照) として機能しない限り、なぜ同じオブジェクトの 50 ほどのクローンを保存する必要があるのか​​、少しわかりません。

オブジェクトの正確なコピーを作成したい場合は、ポリモーフィズムの問題を考慮する必要があります。特定のクラスをサブクラス化する人々が状態メンバーを追加することを許可されている場合、equals や compareTo などの関数ですでに十分な頭痛の種になっています。そのクローンは、特別な処理が必要なもう 1 つのケースです。

私はクローンが常に悪であることに同意しません。時には必要な場合もあります。ただし、サブクラス化の状況では、多くのことが難しくなります。

(機会があれば) Bloch の「Effective Java」を読むことをお勧めします。Bloch のトピックの多くがカバーされています。Bracha の見解は、他の人にあなたのクラスを拡張させるのは良い考えではなく、そうする場合は、彼らがしなければならないことを十分に文書化し、彼らがあなたの指示に従ってくれることを期待する必要があるというものです. それを回避する方法は本当にありません。Traders を不変にすることもできます。

Clone を通常どおりに実装し、Trader から継承してステート メンバーを追加するすべてのユーザーが X メソッドを実装する必要があることをクラス ヘッダーに明確に示します (どちらを指定するか)。

実際の Cloneable をバイパスし、それでも Clone をバイパスするトリックを見つけても、継承の問題を克服することはできません。ここに特効薬はありません。

于 2009-04-26T23:31:18.920 に答える
0

Uri の言う通り、状態を伴うポリモーフィズムは、ワームの大きな缶を開きます。

Cloneable をサブクラス化し、clone() をオーバーライドするのがおそらく最も簡単な方法だと思います。戻り値の型を共変にすることができると思います。

于 2009-04-27T02:49:19.600 に答える
0

1 つのオプション: オブジェクトをシリアライズ可能にできる場合は、オブジェクトを RMI 経由で渡す場合と同様に、シリアライズしてからデシリアライズしてコピーを作成できます。

クイックコピー方法:

public MyObject copy() {
    ObjectOutputStream oos = null;
    ObjectInputStream ois = null;
    try {
        ByteArrayOutputStream bos =  new ByteArrayOutputStream();
        oos = new ObjectOutputStream(bos);
        oos.writeObject(this);
        oos.flush();
        ByteArrayInputStream bin =
            new ByteArrayInputStream(bos.toByteArray());
        ois = new ObjectInputStream(bin);
        return (MyObject)ois.readObject();
    } catch(Exception e) {
        return null;
    } finally {
        try {
            oos.close();
            ois.close();
        } catch (Exception e) {
            return null;
        }
    }
}
于 2009-04-26T23:13:51.333 に答える
-2

1 つの方法は、Java 独自の String のような final クラスにすることです。これにより、クラス Trader のオブジェクトに変更を加えてメモリ内に新しいコピーを作成しますが、サブクラス化することはできなくなります。

もう 1 つの (より良い) 方法は、ファクトリ メソッドを使用して Trader objext を作成およびコピーすることです。これは、デフォルト コンストラクターの使用を許可してはならない、つまりプライベートにすることを意味します。このようにして、クラスが持つインスタンスの数を制御できます。http://en.wikipedia.org/wiki/Factory_methodを参照

public class Trader {

    /* prevent constructor so new cant be used outside the factory method */
    private Trader() {
    }

    /* the factory method */
    public static Trader createTrader(int whatKindOfTrader) {

        switch (whatKindOfTrader) {
        case 0:
            return new Trader1(); // extends Trader
        case 1:
        default:
            return new Trader2(); // extends Trader
        }
        return new Trader3(); // or throw exception
    }
}

別のオーバーロードされたメソッド、または 1 つの Trader を取得してそれを新しいものにコピーし、クローンを置き換える 2 番目の引数を指定することもできます。ところで、デフォルトのオブジェクトの複製を防ぐために、clone() メソッドをオーバーライドして CloneNotSupportedException をスローしたい場合があります。

于 2009-04-26T23:29:24.307 に答える