第15講 クラスの学習その2
第5話 コピーコンストラクタ
私は、今回書籍を購入しないで、ネットでJavaで学習しました。
すばらしいページがたくさんありましたが、
CやC++のプログラミングの経験が20年以上ある私でも、???の場面がたくさんありました。
申し訳ありませんが、2つのサイトからコピーコンストラクタの説明の引用をさせていただきます。
『コピーコンストラクタは、自分自身の型を引数として受け取り、自身の新たなインスタンスを返すコンストラクタです。』
『同じクラスのインスタンスを受け取りそのフィールドの値を新しいインスタンスにコピーするコンストラクタをコピーコンストラクタと呼ぶ。インスタンスのディープコピーに使う。』
この説明は、何度読んでも意味がさっぱりわかりませんでした。
見つけられませんでしたが、それ以上に意味不明の説明もありました。

この呪文としかいいようのない説明のいわんとしていることは、
実はとっても簡単なことです。
どうして、単純な内容を初心者が混乱するような説明をするのか、本当に不思議です。
簡単な内容というのは、コピーコンストラクタとはコピーするときに使う・・・。
意味はこれだけです。
サンプルプログラムと実行結果を示してから何を何にコピーするのかを示しましょう。
<<p.java>>
class p{
  public int i;
  public int j;
  public int k;
  public String l;
  p(){ //空のコンストラクタ ここは後で説明するのでとりあえず無視してください。
  }

  
public void s(int i,int j, int k,String l){
    this.i=i;
    this.j=j;
    this.k=k;
    this.l=l;
  }
  p(p x){ //コピーコンストラクタ xはクラスpから作られるインストラクタ これはint xと同様に理解すればよい。
    i=x.i;
    j=x.j;
    k=x.k;
    l=x.l;
  }
}
<<x.java>>
import java.io.*;
class x{
  public static void main(String args[]){
    p p1=new p();
    p1.s(12,24,36,"等差数列");
    System.out.println("p1.i="+p1.i+" p1.j="+p1.j+" p1.k="+p1.k+" p1.l="+p1.l);
    p p2=new p(p1);
    System.out.println("p2.i="+p2.i+" p2.j="+p2.j+" p2.k="+p2.k+" p2.l="+p2.l);
    p p3=new p(p1);
    System.out.println("p3.i="+p3.i+" p3.j="+p3.j+" p3.k="+p3.k+" p3.l="+p3.l);
  }
}
実行結果
Java

実行結果を見ていただければ、何を何にコピーしているのかは一目瞭然です。
p p2=new p(p1);
でp1のすべての内容をp2にコピーしています。
p p3=new p(p1);
はもうお分かりですね。p1の内容をすべてp3にコピーしているのです。
すべての内容というのは設計書=雛形から実体化されたp1は4つのフィールド=変数をもっています。
3つのint型の変数とString型の変数の4つのフィールドです。
それを丸ごとコピーしているのです。
つまり、コピーコンストラクタの役割は何かと申し上げますと、
新たに雛形から文書を作るときに、
前に作った文書とまったく同一の文書にするということです。
新しいインスタンスを作るときに、それ以前に作ったインスタンスと内容が丸ごと同じインスタンスを作るためにあるのです。
新しいインスタンス=オブジェクト(雛形から作る文書または設計図から作る新しい車)に、
すでに作ってあるインスタンスの内容をコピーすることであるのです。
運動会の通知雛形から、2012年度版と通知を作っておいて、
別の通知を雛形から作る際に、2012年度版の通知の内容を丸ごとコピーする、
つまり、21012年度版通知をコピーするということです。
これがコピーコンストラクタの仕事の内容です。

さて、
  p(){ //空のコンストラクタ ここは後で説明するのでとりあえず無視してください。
  }
は何のためにあるのでしょうか。
実は、
class p{
  int i;
}
のようにクラスを作ったときに、自動的に
  p(){ //空のコンストラクタ ここは後で説明するのでとりあえず無視してください。
  }

空のコンストラクタが作られているのです。
自動的に作られるコンストラクタをデフォルトコンストラクタといいます。
デフォルトコンストラクタは空ですから、何もしません。
何もしないメソッドです。
ところが、引数のあるコンストラクタ
(現在の例では
  p(p x){ //コピーコンストラクタ
    i=x.i;
    j=x.j;
    k=x.k;
    l=x.l;
  }

を作ると、デフォルトコンストラクタは削除されてしまいます。
そうすると引数のあるコンストラクタしか使えなくなり、
    p p1=new p();
がエラーしています。
そこで、デフォルトコンストラクタが削除されないように、
  p(){ //空のコンストラクタ ここは後で説明するのでとりあえず無視してください。
  }

を明示的に定義してあるわけです。
そうすると、コンピュータは(というよりJavaはといった方がよいでしょうか)、
引数のあるコンストラクタp(p x)と引数のないp()コンストラクタの両方をプログラマが必要としていると判断できて、
引数のないデフォルトコンストラクタは、削除されないで済むわけです。

では、何もしない空のデフォルトコンストラクタは意味がないでしょうか。
そうではありません。
<<p.java>>
class p{
  int i;
}
<<x.java>>
import java.io.*;
class x{
  public static void main(String args[]){
    p p1=new p();
  }
}
このとき、デフォルトコンストラクタは仕事をしています。
つまり、何もしないで(インスタンス変数に値を代入しない)で、オブジェクト=インスタンスを作るという仕事をしているのです。
インスタンス変数に値を代入して、オブジェクトを作るには、
<<p.java>>
class p{
  int i;
  p(){
    i=0;
  }

}
のようにデフォルトコンストラクタを明示的に定義しておけばよいのです。

コピーコンストラクタを宣言するには、p(p x)のようにします。
p(p x)って、意味がわからないよという悲鳴が聞こえてきそうです。
次話ではそれの意味を説明してから、様々なコンストラクタの活用を考えることにしましょう。


第4話へ 第6話へ

戻る

VB講義へ
VB講義基礎へ
vc++講義へ第1部へ
初心者のための世界で一番わかりやすいVisual C++入門基礎講座
初心者のための世界で一番わかりやすいVisual Basic入門基礎講座

初心者のための世界で一番わかりやすいVBA入門講義(基礎から応用まで)
初心者のための VC++による C言語 入門 C++ 入門 基礎から応用まで第1部
初心者のための VC++による C言語 入門 C++ 入門 基礎から応用まで第2部
初心者のための VC++による C言語 入門 C++ 入門 基礎から応用まで第3部