Java
CentOS
継承
コンストラクタ
新人プログラマ応援

コンストラクタと継承の利用方法をCentOSで動作させながら学習した

コンストラクタと継承について、自社勉強会で学習した内容をまとめた。

1180506.jpg

コンストラクタ

まず、コンストラクタの説明をする前にインスタンスの状態について確認しておく。
インスタンスを生成した際、フィールドには、初期値が設定されている。何も明示的に設定していない場合は、以下のようになる。

初期値
int型、shot型、long型等の数値の型 0  
char型(文字) \u0000
boolean型             false
int[]型等の配列型         null
String型等のクラス型        null

これでは、以下のようにインスタンスをnewした後に毎回、初期値を代入しなければならず、面倒。

TestClass1.java
.
.


int pt;
boolean ck;


TestClass1 tc_1 = new TestClass1();
tc_1.pt = 100;
tc_1.ck = true;

TestClass1 tc_2 = new TestClass1();
tc_2.pt = 100;
tc_2.ck = true;

TestClass1 tc_3 = new TestClass1();
tc_3.pt = 100;
tc_3.ck = true;

.
.

そこで、インスタンスが生成された直後に自動実行させる性質をもったコンストラクタを使うと以下のように記述を追加するだけで、あとはnewすれば自動実行してくれる。

TestClass1(){
  this.pt = 100;
  this.ck = true;
}

上記のように、クラス名と同名のメソッド名で、メソッド宣言に戻り値(voidも)がないものがコンストラクタとして扱われる。
この生成時に自動実行する仕組みを利用し、CentOSで、以下のようなファイルを作成し、動作検証した。

TestClass1.java
public class TestClass1{

  TestClass1(){
    System.out.println("TestClass1(引数なし)");
  }

  TestClass1(boolean p_a){
    System.out.println("TestClass1(boolean)");
  }

  TestClass1(int p_b){
    System.out.println("TestClass1(int)");
  }

  public static void main(String[] args){
    TestClass1 tc_1 = new TestClass1();
    TestClass1 tc_2 = new TestClass1(true);
    TestClass1 tc_3 = new TestClass1(1);
  }
}

オーバーロードを利用し、引数なし、boolean型引数、int型引数の3パターンを出力する内容を作成した。これをコンパイルし、実行してみる。
# javac TestClass1.java
# java TestClass1

出力結果は、以下のようになる。

TestClass1(引数なし)
TestClass1(boolean)
TestClass1(int)

型により判断し、それぞれのコンストラクタを実行しているのが分かる。このようにインスタンスを生成した際には、何もしなくてもコンストラクタが実行されている。
また、コンストラクタは、何も処理をしないコンストラクタで良いので、すべてのクラスに定義しなければならない。
もしも、定義していない場合は、引数なし処理内容なしのコンストラクタがコンパイル時に自動で追加されるようになっている。
そのため、コンストラクタを定義していなくても、コンパイルエラーにはならず、気付かぬ内に何も処理をしないコンストラクタが、インスタンス生成時に実行されていたのだ。

継承

製造時に、処理内容の似かよったクラスを作ることもある。
部署毎にフィールドの多少変わる大枠の同じクラスや、会員のランク毎に呼ぶメソッドの1つだけ変わるクラスなど、コピペで作業をすると、追加や修正に時間が掛かったり、把握や管理が難しくなる。それを効率よくさせる方法が、継承である。

まず、先ほどのTestClass1.javaをコピーして、TestClass2.javaを作成する。

# cp -p TestClass1.java TestClass2.java
# ls
TestClass1.java  TestClass2.java

内容は、以下のように修正

TestClass2.java
public class TestClass2 extends TestClass1{
  TestClass2(){
    System.out.println("TestClass2(引数なし)");
  }

  TestClass2(boolean p_a){
    System.out.println("TestClass2(boolean)");
  }

  TestClass2(int p_b){
    System.out.println("TestClass2(int)");
  }

  public static void main(String[] args){
    System.out.println("TestClass1のインスタンス");
    TestClass1 tc2_1 = new TestClass1();
    TestClass1 tc2_2 = new TestClass1(true);
    TestClass1 tc2_3 = new TestClass1(2);

    System.out.println("");

    System.out.println("TestClass2のインスタンス");
    TestClass2 tc2_4 = new TestClass2();
    TestClass2 tc2_5 = new TestClass2(true);
    TestClass2 tc2_6 = new TestClass2(2);
  }
}

他クラスを継承するには、クラス宣言の後に「~extends 継承クラス名」を記述する。
これをコンパイルし、実行すると以下のようになる。

# javac  TestClass2.java
# java TestClass2
TestClass1のインスタンス
TestClass1(引数なし)
TestClass1(boolean)
TestClass1(int)

TestClass2のインスタンス
TestClass1(引数なし)
TestClass2(引数なし)
TestClass1(引数なし)
TestClass2(boolean)
TestClass1(引数なし)
TestClass2(int)

TestClass1クラスを継承したことによって、TestClass1をインスタンス生成した箇所は、テスト1のコンストラクタのみが実行され、TestClass2のインスタンス生成をした箇所では、インスタンス生成の最初にかならず、親クラスとなるTestClass1が先に呼ばれてから、TestClass2のコンストラクタが実行されているのが分かる。

継承することの恩恵は、自身で定義していなくてもextendsした親クラスの内容も含めて使えることにある。

以上。