右は、『 Recoed2クラスを継承したRecord3のクラスがある』というのクラス図です。 |
以下にRecord3.javaのコードを示します。
同じrecパッケージ指定なので、
Recoed3.javaも、Record2.javaと同じrecディレクトリの中に作ります。
次のようにRecord3のクラスを作る時、extends キーワードの後にRecord2を指定します。これで、
Record2を継承したクラスになります。
そして、新たにpublic のフィールドとしてint型のtankaを宣言するだけです。
package rec; public class Record3 extends Record2 { public int tanka; //単価 }
なお、rec以外のpackageに所属させることもできますが、ここでは同じにしました。
これによりに先頭で、import rec.Record2;の記述が不要になります。
(他のpackageに所属させる場合は必要になります。)
以下のプログラムで、Record3クラスを利用例を示します。(右が実行結果です。)
import rec.Record3; public class Test { public static void main(String[] arg){ Record3 r1 = new Record3(); //レコード2のコンストラクタが内部で実行されいる。 r1.init("A01", 10);//Record2の機能を利用 r1.tanka = 100; r1.display(1);//Record2の機能を利用 System.out.printf("\t単価:%d\n", r1.tanka); } } |
D:\java>java Test 1番目レコード 商品コード:A01 数量:10 単価:100 D:\java> |
さて、
上記 の2行は、
Record3専用のinitメソッドを作ることで1行で済ませることができます。
同様に上記 の2行は、
Record3専用のdisplayメソッドを作ることで1行で済ませることができます。
以下で、そう変更したRecoed3.javaとクラス図を示します。
package rec; public class Record3 extends Record2 { public int tanka; //単価 public void init(String shoCode, int n, int price) { super.init(shoCode, n);// スーパークラスのinitを呼び出す //この場合はsuperを省略できます tanka = price; } public void display(int n) { super.display(n);// スーパークラスのdisplayを呼び出す //この場合はsuperを省略でません。省略すると、 //自身を呼び出す(再帰)ため無限ループなり、 //StackOverflowErrorの実行エラーになる System.out.printf("\t単価:%d\n", tanka); } } |
Record3でメソッドを追加していますが、
その場合でもなるべくスーパークラスであるRecord2の機能を利用するように作成しています。
メソッドの中で、得にスーパークラスのメソッドを明示的に使いたい場合は、super
のキーワードを使います。このsuperキーワードを使わなくても、同じ操作(引数や戻りなど)のメソッドがなければ、
引き継いでいるスーパークラスのメソッドが使えます。
initの場合は、引数2つのinitメソッドが
Record3に無いので、super.は書かなくてもRecord2のinitメソッドが呼び出せます。
( this.init(shoCode, n)と書いた場合も同じで、Record2のメソッド呼び出しになります。)
対して、displayは全く同じ操作(引数や戻りなど)のメソッドがあるので、明示的に
super
のキーワードを使わないと、Record2の機能が呼び出せないことになります。
以下のこのクラスを使うように変更したTest.javaと実行結果を示します。
import rec.Record3; public class Test { public static void main(String[] arg){ Record3 r1 = new Record3(); //レコード2のコンストラクタが内部で実行されいる。 r1.init("A01", 10, 100);//Record3の機能を利用 r1.display(1);//Record3の機能を利用 } } |
D:\java>java Test 1番目レコード 商品コード:A01 数量:10 単価:100 D:\java> |
なお、 上記のプログラムを、次のように実行できるようにするには どうしたらよいでしょうか?
import rec.Record3; public class Test { public static void main(String[] arg){ Record3 r1 = new Record3("A01", 10, 100); r1.display(1);//Record2の機能を利用 } }
シンボルを見つけられません。
シンボル: コンストラクタ Record3(java.lang.String,int,int)
new Record3("A01", 10, 100);の所でコンパイルエラとなります。
つまりRecord3のコンストラクタを追加すればよいのです。
Record3.javaに次のコードを追加すればよいでしょう。
public Record3(String shoCode, int n, int price) { super(shoCode, n); // スーパークラスのコンストラクタを呼び出し tanka = price; }
派生クラスのコンストラクタから、 そのスーパークラス(派生元クラス)のコンストラクタを呼び出す場合は、 上記のように、コンストラクタ内の { 内先頭行で super( 引数 )の 表現で書かなければいけない規則になってます。
また、上記引数ありコンストラクタを作った時より、デフォルトコンストラクタが
使えなくなります。
つまり、new Record3()のような生成ができなくなります。
これは、Record3.javaに次の引数なしコンストラクタのコードを追加することで可能になります。
public Record3()//引数なしコンストラクタ { //スーパ(Recoed2)クラスのコンストラクタ書いていなくても実行される。 }
なお、上記の引数なしコンストラクタや、引数ありコンストラクタで明示的にスーパクラスのコンストラクタを
呼びださない場合は、
書いていなくても自動的にスーパクラスの引数なしコンストラクタが呼び出される
仕組みになっています。
よって この場合、
スーパクラスのRecord2の引数なしコンストラクタが使えるように作られていないと
コンストラクタでシンボルを見つけられません。の
コンパイルエラーとなり、注意が必要です。
以上のメソッドやコンストラクタ追加により、Record3のクラス図は次のようになります。