4

The Java Programming Language book の次のコードを検討してください。

public class MyClass extends HerClass implements Cloneable {
   public MyClass clone()
       throws CloneNotSupportedException {
       return (MyClass) super.clone();
   }
   // ...
}

オーバーライドする clone() 関数がすでに戻り値の型を MyClass として種付けしている場合、return ステートメントでそれを再度指定する要件は何ですか? また、Myclass のスーパー クラス オブジェクトのクローンが作成されているため (clone() が wrt スーパークラスと呼ばれているため)、どうして Myclass 型になるのでしょうか?

前もって感謝します

4

4 に答える 4

1

最初の簡単な質問: なぜ にsuper.clone()キャストされるのMyClassですか? これは、 の宣言がHerClass.clone()の戻り値を指定したHerClassためです。そのため、正しい型にキャストする必要があります。

さて、より難しい質問:super.clone()実際に のインスタンスを返すにはどうすればよいMyClassでしょうか? 私は実際に答えを見つけるのに苦労しましたが、Joshua Bloch の「Effective Java」で答えを見つけることができました。Object.clone()その背景にはまだよくわからない「魔法」があります。

本のアイテム11:

実際には、プログラマーは、クラスを拡張してサブクラスから super.clone を呼び出すと、返されるオブジェクトはサブクラスのインスタンスになると想定しています。スーパークラスがこの機能を提供できる唯一の方法は、super.clone を呼び出して取得したオブジェクトを返すことです。clone メソッドがコンストラクターによって作成されたオブジェクトを返す場合、そのオブジェクトのクラスは間違っています。したがって、非 final クラスで clone メソッドをオーバーライドする場合は、 super.clone を呼び出して取得したオブジェクトを返す必要があります。クラスのすべてのスーパークラスがこの規則に従う場合、super.clone を呼び出すと、最終的に Object の clone メソッドが呼び出され、適切なクラスのインスタンスが作成されます。

私はもともと、あなたが常に を呼び出さなければならないことを知らずに、プログラムを書くことであなたの質問に答えようとしましたsuper.clone()。私の自作の clone メソッドは、コンストラクター ( ) から生成されたHerClassの新しいインスタンスを返していました。コードはコンパイルされましたが、キャストしようとしたときに実行に失敗しました。サブタイプの 1 つのインスタンスである値を返すことができるのは、チェーンされたメソッドだけです。HerClassnew HerClass()(MyClass) super.clone()Object.clone()

HerClass.clone()ifが明示的に実装されていない場合、デフォルトでは単純に を返すことに注意してくださいObject.clone()。デフォルトのメソッドにはprotectedアクセスがありますが、サブクラスから呼び出しているので問題ありません。

于 2011-08-28T19:01:33.157 に答える
1

これは、 Objectclone()のメソッドが を返すためです。ただし、オブジェクトを拡張するため、clone() でサブクラスを返すことができます。メソッドがこのように見える場合ObjectMyClass

public Object clone()

その後、それはまだ有効な複製可能なオブジェクトであり、機能します。何もキャストする必要はありません。インターフェイスCloneableは単なるマーカー インターフェイスです。つまり、実際にはメソッドがありません。

于 2011-08-28T17:41:21.557 に答える
1

クラス Object のオブジェクトを返すためclone()、正しい型にキャストする必要があります。しかし、それが MyClass 型のオブジェクトであることはわかっているので、キャストは正しいです。

于 2011-08-28T17:17:26.923 に答える
1

理論的には正しいです。関数の戻り値の型を指定する必要があるため、コンパイラは自動的に修正を試行して実行できます。一方、明示的な変換を要求すると、考えられるエラーを特定するのに役立ちます。

特定の要件がない限りclone()、クラスのメソッドはObjectすでに正しいことを行っています。つまり、正しいクラスのオブジェクトを作成し、複製されたオブジェクトのすべての非静的属性をコピーします。Objectただし、コンパイル時にその型がクラス自体に認識されていないため、派生型として返すことはできません。

メソッドがすべてのクラスに自動的に提供される可能性があることは事実ですが、clone()メソッドを使用可能にしたくない場合や、デフォルトの動作をオーバーライドしたい場合があります。たとえばid、複製された場合でも、クラスのインスタンスごとに異なる属性がクラスにある場合があります。メソッドをオーバーライドするclone()必要があるため、そのような機能を実装できる場所が得られます。

于 2011-08-28T17:39:26.690 に答える