クラスの継承
サブクラスのコンストラクタ
サブクラスには、コンストラクタの明記が必要です。
サブクラスのコンストラクタには、super() の記述が必要です。
super()
目次
1. コンストラクタは暗黙的に継承されない
サブクラスは、スーパークラスのメンバを暗黙的に継承しますが、
コンストラクタだけは明示する必要があります。
//Animal_01.java
public class Animal_01{
protected static String group = "生き物です。";
protected String name;
public Animal_01(){
this("無名");
}
public Animal_01(String name){
this.name = name;
}
public static void printGroup(){
System.out.println(group);
}
public void printName(){
System.out.println(name + "だぞ! ガオー!");
}
}
↓↓↓ これで Animal_01と同じ。↓↓↓
//Dog_02.java
public class Dog_02 extends Animal_01{
public Dog_02(){ //コンストラクタの明示
super(); //Animal_01() を呼んでいます。
}
public Dog_02(String name){ //コンストラクタの明示
super(name); //Animal_01(String name) を呼んでいます。
}
}
普通のメソッドや変数は
記載なしで継承できるのに?
そう。
そうゆう仕様なんで
仕方がない。
//Driver_02.java
public class Driver_02{
public static void main(String[] args){
Dog_02 dog_01 = new Dog_02("フレンダー");
Dog_02 dog_02 = new Dog_02();
dog_01.printName();
dog_02.printName();
}
}
Animal_01.java、
Dog_02.java、
Driver_02.java、の3つのファイルを
wsフォルダに保存して実行します。
コマンドライン
>cd ws
ws>javac -encoding UTF-8 Driver_02.java
ws>java Driver_02
フレンダーだぞ! ガオー!
無名だぞ! ガオー!
2. super はスーパークラスのこと
superとは
スーパークラスの事だ。
super の後ろに「()」丸かっこを続けると、スーパークラスのコンストラクタを示します。
重要
super() はスーパークラスのコンストラクタ
スーパークラスのコンストラクタが、オーバーロードによって複数存在する場合には、
「super()」に与える引数で、呼び出すコンストラクタを指定します。
this() とそっくりっスね。
Point
super() はスーパークラスのコンストラクタ
this() は自分自身のコンストラクタ
3. super() 又は this() が必要
super() の記述
サブクラスのコンストラクタの最初に super() が必要です。
this() の利用
最終的に super() が参照されるのであれば、this() も利用できます。
この場合も、サブクラスのコンストラクタの最初 に this() を書きます。
サブクラスのコンストラクタには、
使える コンストラクタを
書いておくってことっすか?
そうそう、
こんな感じなら、
this()も使えるぞ。
//Dog_02B.java
public class Dog_02B extends Animal_01{
public Dog_02B(){
this("ナナシノゴンベエ");
}
public Dog_02B(String name){
super(name);
}
}
//Driver_02B.java
public class Driver_02B{
public static void main(String[] args){
Dog_02B dog_01 = new Dog_02B("フレンダー");
Dog_02B dog_02 = new Dog_02B();
dog_01.printName();
dog_02.printName();
}
}
Animal_01.java、
Dog_02B.java、
Driver_02B.java、の3つのファイルを
wsフォルダに保存して実行します。
コマンドライン
>cd ws
ws>javac -encoding UTF-8 Driver_02B.java
ws>java Driver_02B
フレンダーだぞ! ガオー!
ナナシノゴンベエだぞ! ガオー!
this()の時と同じで、
「コンストラクタの最初」
というのもポイントだ。
これは OUT!
//Dog_02NG.java
public class Dog_02NG extends Animal_01{
public Dog_02NG(String name){
System.out.println("Dog_02NG");
super(name); //コンストラクタの最初に super がない
}
}
//Driver_02NG.java
public class Driver_02NG{
public static void main(String[] args){
Dog_02NG dog_01 = new Dog_02NG("フレンダー");
}
}
Animal_01.java、
Dog_02NG.java、
Driver_02NG.java、を
wsフォルダに保存して実行します。
コマンドライン
>cd ws
ws>javac -encoding UTF-8 Driver_02NG.java
.\Dog_02NG.java:6: エラー:
superの呼出しはコンストラクタの先頭文である必要があります
super(name); //コンストラクタの最初に super がない
^
エラー1個
なるほどねー。
4. super() の省略
重要
サブクラスのコンストラクタに、super() を書かなかった場合には、
引数なしの super() が最初にあるものとして解釈されます。
これ、
知らないと
割と混乱するやつ。
//Cat_03.java
public class Cat_03 extends Animal_01{
public Cat_03(String name){
//super()が無い
}
}
↓↓↓ 以下のように解釈されます。↓↓↓
Cat_03クラスの解釈
//Cat_03.java
public class Cat_03 extends Animal_01 {
public Cat_03(String name){
super();
}
}
//Driver_03.java
public class Driver_03{
public static void main(String[] args){
//引数を与えても「super();」が呼ばれる
Cat_03 cat03 = new Cat_03("ニャース");
cat03.printName();
}
}
Animal_01.java、
Cat_03.java、
Driver_03.java、を
wsフォルダに保存して実行します。
コマンドライン
>cd ws
ws>javac -encoding UTF-8 Driver_03.java
ws>java Driver_03
無名だぞ! ガオー!
「無名だぞ!」に
なっちゃいましたね。
だな。
Animal_01の
引数なしのコンストラクタを
呼び出しているから、
name変数に「無名」が入った。
"ニャース"は使われない。
コンストラクタは
ちゃんと書いた方が良さそうね。
5. デフォルトコンストラクタ
サブクラスでもデフォルトコンストラクタを省略できます。
サブクラスのデフォルトコンストラクタの中身は、「super() のみ」と解釈されます。
//Cat_04.java
public class Cat_04 extends Animal_01 {
//コンストラクタの記述なし
}
↓↓↓ 以下のように解釈されます。↓↓↓
デフォルトコンストラクタの解釈
//Cat_04.java
public class Cat_04 extends Animal_01 {
//デフォルトコンストラクタ
public Cat_04(){
super();
}
}
//Driver_04.java
public class Driver_04{
public static void main(String[] args){
Cat_04 cat04 = new Cat_04();
cat04.printName();
}
}
Animal_01.java、
Cat_04.java、
Driver_04.java、を
wsフォルダに保存して実行します。
コマンドライン
>cd ws
ws>javac -encoding UTF-8 Driver_04.java
ws>java Driver_04
無名だぞ! ガオー!
この場合は暗黙的に
コンストラクタが
使えるのね。
コンストラクタ継承の例外というより、
デフォルトコンストラクタの一種だな。
6. サンプルコード
引数のないサブクラスのコンストラクタで、
引数が Stringのコンストラクタを
呼んだ例だ。
Unknown_01クラスは、Animal_01クラスのサブクラスです。
Unknown_01クラスのコンストラクタには、引数がありません。
でも、super() の引数に「"謎の生物X_"+ (++no)」を与えていますので、
Animal_01クラスの引数が Stringのコンストラクタを呼び出しています。
Unknown_01をインスタンス化するたびに
変数「no」がインクリメントされる。
//Unknown_01.java
public class Unknown_01 extends Animal_01 {
public static int no = 0; //カウントのための static変数
public Unknown_01(){
super("謎の生物X_"+ (++no));
}
}
サブクラスのコンストラクタと
スーパークラスのコンストラクタで
引数が違っていても大丈夫なのね。
//Driver_05.java
public class Driver_05{
public static void main(String[] args){
Animal_01[] animalArray = new Animal_01[9];
for(int i=0; i<animalArray.length; i++){
animalArray[i] = new Unknown_01();
}
//すべての要素で printNameメソッドを実行
for(int i=0; i<animalArray.length; i++){
animalArray[i].printName();
}
}
}
Animal_01.java、
Unknown_01.java、
Driver_05.java、を
wsフォルダに保存して実行します。
コマンドライン
>cd ws
ws>javac -encoding UTF-8 Driver_05.java
ws>java Driver_05
謎の生物X_1だぞ! ガオー!
謎の生物X_2だぞ! ガオー!
謎の生物X_3だぞ! ガオー!
謎の生物X_4だぞ! ガオー!
謎の生物X_5だぞ! ガオー!
謎の生物X_6だぞ! ガオー!
謎の生物X_7だぞ! ガオー!
謎の生物X_8だぞ! ガオー!
謎の生物X_9だぞ! ガオー!
それぞれのインスタンスの「"謎の生物X_"+ (++no)」が表示されました。
おぉぉ。
謎の生物大量発生!
お疲れ様でした。