2013-04-03 8 views
6

私はつまり、私は仕事にこのような何かを必要とする、多型クローニング(深いコピー)と私のクラスを装備する必要があります:Javaクローン()メソッドは、多型クローニングを実現する唯一の方法ですか?

original.clone()は深いコピーを作成するための任意のメカニズム、および実際の型によって置換することができる
SuperType original = new SubType(); 
SuperType copy = original.clone(); 

copyの値はであるため、もSubTypeであるため、SubTypeとなります。

clone()メソッドとCloneableインターフェイスはこれを実現する唯一の方法ですか?実際のクラスは実行時にのみ認識されるため、ファクトリメソッドとコピーコンストラクタは使用できません。それらのシリアライズ - デシリアライズアプローチを除いて、他に提案されているメソッドがありますか?clone()メソッドよりもさらに悪い黒い魔法ですJava deep-cloning library?あなたがCloneableインターフェイスが気に入らない場合は

おかげで、ペトル

+0

クローン作成するオブジェクトを渡すことができるコンストラクタを作成することはできません。 – Justin

+0

@gangqinlaohu確かに、元のクラスが実際には 'SubType'か、' SubType2'であればコードを書く時は分からないので、 'new SubType(original)'を呼び出す必要があります。 、または 'SubSubType'です。 – Posa

答えて

4

実際にオブジェクトのclone()メソッドでは、protectedであるため、多態性呼び出しを実行できません。 Cloneableの実装には、clone()メソッドが含まれていないために使用できません。

コピーコンストラクタを呼び出すクローンクラスのポリモーフィックメソッドを提供することにより、ポリモフィッククローニングを行うことができます。

abstract class SuperType { 
    public SuperType(SuperType t) { 
    } 

    public abstract SuperType deepCopy(); 
} 

class SomeType extends SuperType { 

    SomeType(SomeType t) { 
     //copy constructor 
    } 

    @Override 
    public SomeType deepCopy() {       
     return new SomeType(this); 
    } 
} 

... 

SuperType original = new SubType(); 
SuperType copy = original.deepCopy(); //the deepCopy is called on children classes 

参照:

Joshua Block's opinion on cloning vs. copy constructor

+0

OK、それはうまくいくでしょう。しかし、これは 'clone()'の使用とどのような意味で違いますか? 'deepCopy()'メソッドはそれとは別の名前ではありませんか? 'deepCopy()'で 'clone()'と同じことをすることはできませんか? – Posa

+0

@Posa Cloningは、コピーコンストラクタを必要とせずにオブジェクトのコピーを提供するためのJavaの「組み込みの」方法です。プログラマーの人生をもっと楽にしようとしましたが、IMOはそうではありません。はい、あなたが 'clone()'をオーバーライドするときに細心の注意を払うならば(Joshua BlockのEffectiva Javaにはその章があります)、同じ結果が得られるはずです。 – dcernahoschi

1

は、あなたは、単にあなたがあなた自身のインターフェイスを作成することができ、すべてのサブタイプ

class SuperType { 

    public SuperType copy() { 
       ... 
    } 
} 
0

にスーパータイプとそれを実装するためのコピー方法を追加することができます。各クラスは、正しいタイプの新しいインスタンスを作成する責任があります。

+0

「Clonable」が好きではないという事実ではありません。私は、私がJ. Blochの本を読んだにもかかわらず、おそらくクローンに関連して発行されたものを理解していないと思う。基本的に私の独自のインターフェースをClonableと同じ目的で考案するのはなぜですか?あるいは、私自身のインターフェースの目的がClonableのものと異なるだろうか? – Posa

+0

さて、あなたの質問は、 "これはclone()メソッドとCloneableインターフェイスがこれを実現する唯一の方法ですか?"です。 clone()メソッドが正常であれば、それを使用してください。ただし、カスタムインターフェイスを使用すると、ジェネリックスを利用できます。 – WilQu

2

あなたのコードが動作するためには、そのコードは、どちらかSuperTypeクラスまたはサブクラスの内部で、またはあなたのSuperTypeタイプは、公共clone()メソッドを持っている必要があります。公開clone()メソッドは自動的には存在しないため、実装する必要があります。あなたはそのことに関して何か他のものと呼ぶことができます。 copy()

あなたの質問は、その多型クローニングを行うようにそのclone()(またはそれを呼び出す方法)メソッドを実装する方法です。

Java開発者が意図した方法は、super.clone()を呼び出して、継承階層のすべてのクラスが同様に多態的な複製を実行するためにclone()を実装したとします。これは最終的に、保護されたObject.clone()メソッドに到達します。これは、多形性クローニングの魔法です。 Object.clone()が例外をスローしないようにするには、クラスにCloneableインターフェイスを実装する必要があります。

ただし、他の方法もあります。たとえば、すべてのサブクラスにデフォルトコンストラクタがあると仮定すると、this.getClass().newInstance()のようなことができます。これにより、適切なクラスのオブジェクトが作成されますが、フィールドはコピーされません。クローンメソッドはすべてのフィールドをコピーする必要があり、サブクラスはクローンメソッドをオーバーライドしてフィールドなどをコピーする必要があります。この場合、Cloneableインターフェイスが実装されているかどうかは関係ありません。

もう1つの方法は、クラスがSerializableであると仮定して、thisをシリアル化してシリアル化解除することです。これにより、継承可能なすべてのフィールドが持ち越された多型クローンが作成されます。

関連する問題