- PR -

自作クラスでObjectクラスのメソッドを使用したい。

投稿者投稿内容
初芽
会議室デビュー日: 2005/07/03
投稿数: 15
投稿日時: 2005-07-06 18:44
自作クラスで、Objectクラスのcloneメソッドを利用したいのですが、うまくいきません。
自作クラスで、オブジェクトを一つ生成し、そのオブジェクトのコピーを作成したいと考え、cloneメソッドを利用しようとしています。
―――――――――――――――――――――――――――――――
//車クラス
class Car{
int num;
double gas;
//↓コピーを作成するメソッド
static Car copy(Car car1)throws CloneNotSupportedException{
return (Car)car1.clone();
}
}
//車クラスのインスタンスを作成する
class Sample1{
public static void main(String args[])throws CloneNotSupportedException{

Car car1;
car1 = new Car();
car1.num = 1234;
car1.gas = 20.5;

Car car2;
car2 =Car.copy(car1);//コピーを作成するメソッドを呼び出す

System.out.println("車のナンバーは"+ car1.num + "です。");
System.out.println("ガソリン量は"+ car1.gas + "です。");

System.out.println("車のナンバーは"+ car2.num + "です。");
System.out.println("ガソリン量は"+ car2.gas + "です。");
}
}
―――――――――――――――――――――――――――――――――――
コンパイルはできて、実行時にエラーが出ます。
エラーは下記です。
Exception in thread "main" java.lang.CloneNotSupportedException: Car
at java.lang.Object.clone(Native Method)
at Car.copy(Sample1.java:6)
at Sample1.main(Sample1.java:19)
―――――――――――――――――――――――――――――――――――
―――――――――――――――――――――――――――――――――――
どうか、よろしくお願いいたします。
スフレ
ぬし
会議室デビュー日: 2005/05/27
投稿数: 281
お住まい・勤務地: 東京
投稿日時: 2005-07-06 18:46
自分でCarのclone()を実装する必要があります。
K
大ベテラン
会議室デビュー日: 2004/04/07
投稿数: 174
投稿日時: 2005-07-06 18:50
http://www.nurs.or.jp/~sug/soft/java/java23.htm
↑このあたりに書いてあります
初芽
会議室デビュー日: 2005/07/03
投稿数: 15
投稿日時: 2005-07-06 19:18
おかけ様で、完成しました!
ありがとうございました。

作成して、出てきた疑問なのですが、
結局、コンストラクタも作成しなければならないのですね?
あまり、このような事はしないのでしょうか。
同じインスタンスを生成するならば、クラスを作成して初期値を入れておいたらよい
ということでしょうか?

完成したプログラムですが、無駄は多いのでしょうか。
もっと簡略化して書けるのでしょうか?
――――――――――――――――――――――――――――――――――
――――――――――――――――――――――――――――――――――
class Car implements Cloneable{
int num;
double gas;
Car(Car car1){
num = car1.num;
gas = car1.gas;
}
Car(){}
static protected Car clone(Car car1){
return new Car(car1);
}
}
class Sample1{
public static void main(String args[])throws CloneNotSupportedException{

Car car1;
car1 = new Car();
car1.num = 1234;
car1.gas = 20.5;

Car car2;
car2 = Car.clone(car1);

car1.num = 0000;
car2.gas = 10.0;

System.out.println("車のナンバーは"+ car1.num + "です。");
System.out.println("ガソリン量は"+ car1.gas + "です。");

System.out.println("車のナンバーは"+ car2.num + "です。");
System.out.println("ガソリン量は"+ car2.gas + "です。");
}
}
――――――――――――――――――――――――――――――――――
――――――――――――――――――――――――――――――――――
スフレ
ぬし
会議室デビュー日: 2005/05/27
投稿数: 281
お住まい・勤務地: 東京
投稿日時: 2005-07-06 19:34
無駄がないかと言われれば、numとgasを違う値にするのにcar2をクローンで生成することが無駄そのもののような(笑)

自分とmogeさんの心づもりとしては、
コード:
public Object clone() {
    return new Car(this);
}
  :
  :
car2 = (Car)car1.clone();


こんな感じです。

コンストラクタを増設したくないなら、
コード:
public Object clone() {
    Car c = new Car();
    c.num = this.num;
    c.gas = this.gas;
    return c;
}


こんなんで。
かつのり
ぬし
会議室デビュー日: 2004/03/18
投稿数: 2015
お住まい・勤務地: 札幌
投稿日時: 2005-07-06 19:38
ディープコピーの必要がなければ、実装は不要です。
コード:
class Car implements Clonable{
    int num;
    double gas;
}



これだけで、クローンの作成が可能ですが
参照型のフィールドを持つ場合は、
そのフィールドの参照まではクローンの対象とはなりません。
uk
ぬし
会議室デビュー日: 2003/05/20
投稿数: 1155
お住まい・勤務地: 東京都
投稿日時: 2005-07-06 19:42
なぜこのような結論になるんですか? これだとClonableは関係ないですよね。
Object#cloneを利用できるようにするために必要なのは、
・Clonableインタフェースを実装すること
・cloneメソッドをオーバライドすること
です。実際には以下のようなコードになります。利用側のコードはご自分で考えてください。

コード:
class Car implements Cloneable{
  int num;
  double gas;
  public Object clone(){
    Car car = new Car();
    car.num = this.num;
    car.gas = this.gas;
    return car;
  }
}

YOU@IT
ぬし
会議室デビュー日: 2002/03/29
投稿数: 284
お住まい・勤務地: 大阪
投稿日時: 2005-07-06 20:23
スーパークラスの#clone()を呼び出した方がいいのではないでしょうか?

コード:
class Car implements Cloneable{
  int num;
  double gas;
  /** ミュータブルオブジェクト */
  MutableObject mutableObj;

  public Object clone(){
    /* 
     * super.clone()によって、コピーインスタンスが生成される
     * コピーインスタンスが、ディープコピーされているかはスーパークラスの
     * #clone()の実装に依存する
     */
    Car car = (Car)super.clone();

    /* プリミティブ値は、super.clone()でコピー済みなので、ここではコピー不要 */
    // car.num = this.num;
    // car.gas = this.gas;

    /* ミュータブルオブジェクトは、再帰的に#clone()が必要 */
    car.mutableObj = this.mutableObj.clone();

    return car;
  }
}



numとgasはプリミティブ値なので、かつのりさんご指摘のように、これだけなら
ディープコピー実装は不要ですね。

上記例のように、ミュータブルオブジェクト(状態が変化しうるオブジェクト)を
フィールドに持つ場合は、それを再帰的に#clone()しないと、完全な
ディープコピーにはなりません。

イミュータブルオブジェクト(StringやInteger等、状態が変化しないオブジェクト)で
あれば、再帰的に#clone()しなくても、問題になりません。

書籍 Effective Java 等に詳細な説明があります。

スキルアップ/キャリアアップ(JOB@IT)