clone() メソッドの実装(1)−基本的な実装方法
Java で Prototype パターンを実現するために必要な、clone() メソッドについて記述します。
clone() メソッドの仕様
いずれも、必須ではないそうです。(´・ω・)
clone() メソッドの特殊性
clone() メソッドは、これまで説明した equals() メソッドや hashCode() メソッドとは異なる特徴を持っています。
一筋縄ではいかないようになっています。
基本的な実装方法
実装例
import java.util.Date; // ●Cloneable を実装すること! public class ComplicateObject implements Cloneable { // fields private boolean booleanValue; private byte byteValue; private char charValue; private short shortValue; private int intValue; private long longValue; private float floatValue; private double doubleValue; private String stringValue; private Date dateValue; @Override public ComplicateObject clone() { // J2SE 1.5 以降は、当クラスのインスタンスを直接返してよい。 // こうすれば、client 側で毎回キャストする必要がなくなり便利。 ComplicateObject result = null; try { // super.clone() が、各フィールドをコピーしてくれる。 result = (ComplicateObject) super.clone(); // オブジェクトの参照の場合、clone() を再帰呼び出しすればよい(deep copy)。 // ※String は immutable なので、特別 clone() を呼ぶ必要はない。そもそも clone() を呼び出せない。 result.dateValue = (Date) this.dateValue.clone(); } catch (CloneNotSupportedException cnse) { // Cloneable を implement しないと発生する。通常発生しない。 // Cloneable を implement すれば発生しないことを仕様として検証済なので、特にテストは不要。 // ※定義上発生しない状態にしておけば、client への負担を減らせるので吉。 } return result; } // getter/setter/constructor は省略 }
動作確認
以下のテストケースは、正常に動作します。
public void testClone() { ComplicateObject original = new ComplicateObject(); original.setBooleanValue(true); original.setByteValue*1; assertTrue(original.equals(copy)); // copy した値の検証 assertTrue(copy.getBooleanValue()); assertEquals( 1, copy.getByteValue()); assertEquals( '2', copy.getCharValue()); assertEquals( 3, copy.getShortValue()); assertEquals( 4, copy.getIntValue()); assertEquals( 5, copy.getLongValue()); assertEquals( 6.0f, copy.getFloatValue()); assertEquals( 7.0, copy.getDoubleValue()); assertEquals( "8", copy.getStringValue()); assertEquals( date, copy.getDateValue()); // deep copy の検証 assertFalse(date == copy.getDateValue()); }
補足
clone() メソッド の基本的な実装は、上記で特に問題ないです。
ですが、clone() メソッドには色々なテクニックがありますので、後日それらについて触れていこうと思います。
*1:byte)1); original.setCharValue('2'); original.setShortValue((short)3); original.setIntValue(4); original.setLongValue(5); original.setFloatValue(6); original.setDoubleValue(7); original.setStringValue("8"); Date date = new Date(); original.setDateValue(date); // copy ComplicateObject copy = original.clone(); // 規約に合致していることの検証 assertFalse(original == copy); assertEquals( original.getClass(), copy.getClass(