LinkedListにクローンを実装します
質問
私はaを実装しようとしています clone()
aのメソッド DoubleLinkedList
. 。さて、問題は、「コンベンション」によってそれを実装することは、単に新しいものを作成するよりもはるかに面倒だということです DoubleLinkedList
そして、現在のDoubleLelinkEdListのすべての要素でそれを埋めます。
それをするときに私が見ていない不便なことはありますか?
これが私の現在のアプローチです:
@Override
public DoubleLinkedList<T> clone() {
DoubleLinkedList<T> dll = new DoubleLinkedList<T>();
for (T element : dll) {
dll.add(element);
}
return dll;
}
これが大会によるものです:
@Override
public DoubleLinkedList<T> clone() {
try {
DoubleLinkedList<T> dll = (DoubleLinkedList<T>)super.clone();
//kinda complex code to copy elements
return dll;
} catch (CloneNotSupportedException e) {
throw new InternalError(e.toString());
}
}
解決
あなたが正しく指摘しているように、条約は常に電話することです super.clone()
の実装の開始 clone()
. 。から APIドキュメントオン Object#clone()
:
慣習により、super.cloneを呼び出すことにより、返されたオブジェクトを取得する必要があります。クラスとそのすべてのスーパークラス(オブジェクトを除く)がこの慣習に従う場合、x.clone()。getClass()== x.getClass()の場合です。
あなたの最初の試み(使用せずに super.clone()
)次の問題があります。
私が持っていると仮定します
class IntDoubleLinkedList extends DoubleLinkedList<Integer> implements Cloneable
(そしてそれ IntDoubleLinkedList
無効にすることを気にしません clone()
)そして、次のコードを実行します。
IntDoubleLinkedList idll = new IntDoubleLinkedList();
IntDoubleLinkedList idll2 = (IntDoubleLinkedList) idll.clone();
何が起こるか?のクローン方法 君の DoubleLinkedList
実行されます、それがsuper.clone()を通過しない場合、のインスタンスを返します DoubleLinkedList
次に、にキャストすることはできません IntDoubleLinkedList
. a ClassCastException
投げられます!
それで、どうしますか super.clone()
この問題を解決しますか?まあ、誰もが電話の慣習に固執しているなら super.clone()
オーバーライデンクローン法では、 Object.clone()
最終的に呼び出され、この実装は適切なタイプのインスタンスを作成します(IntDoubleLinkedList
この場合)!
他のヒント
他の人が説明したように、あなたがオーバーライドするつもりなら clone
あなたはその契約に従うべきです。
あなたが現在持っている方法が好きなら、ただ作る DoubleLinkedList
いいえ Cloneable
実装をコピーコンストラクターまたは静的な工場メソッドに変えます。静的な工場法には、一般的なタイプの引数の推測を少し型にするという追加の利点があります。
詩 LinkedList
は 二重にリンクされたリスト。
新しいリストを作成してソースからすべての要素を追加してそれを行う場合、次のようなことをしてください。
DoubleLinkedList<Foo> l1 = new DoubleLinkedList<Foo>();
l1.add (new Foo(params));
DoubleLinkedList<Foo> l2 = l1.clone();
Foo foo = l2.get(0);
foo.setProperty("new Value");
foo.propertyは両方のリストで「新しい値」になります(同じ逆の方が同じです。L1で変更すると、L2に変更が表示されます)。正しい方法は、すべての要素を実際にクローンし、クローンを追加してリストが独立していることを確認することです。これは、要素のプロパティを変更、移動、リストから削除する場合ではなく、要素のプロパティを変更する場合にのみ発生することに注意してください。
編集:リンクリストであるため、次の要素/以前の要素は要素のプロパティであるため、追加、削除、削除、両方のリストに影響することに気付きました。
「慣習」が呼び出す理由です super.clone()
クローンされたオブジェクトの究極のタイプが、クローン化されているオブジェクトと一致するようにすることです。たとえば、自分の新しいものをインスタンス化する場合 DoubleLinkedList
の中に clone()
方法、今のところそれはいいことですが、後でサブクラスがオーバーライドできない場合 clone()
それは最終的にクローンを返すことになります DoubleLinkedList
独自のクラスの代わりに。 (おそらく、追加のフィールドをクローン化することもできません。したがって、より大きな問題があります。)
その意味では、従来の方法が好まれており、実際に不格好です。
ただし、どちらの実装も同様の問題を抱えています。データ構造を深くコピーしていません。クローンは浅い警官です。これはおそらく発信者が期待するものではありません。あなたはそれぞれの値を通過して交換する必要があります DoubleLinkedList
値のクローンを使用し、同様に他の非微小フィールドについても。
その意味で、従来の方法はここで間違った結果をもたらすでしょう! 3番目の方法が必要です。あなたの最初の方法は、おそらくあなたが追加する必要があることを除いて、おそらくちょうどうまくいっています element.clone()
例えば。