第13章 クラスの継承
継承に関する基本的な考え方について説明します
homepage
# **クラスの継承** *** クラスの継承とは、クラスが保持しているメンバやメソッドの内容を他のクラスで継承することを指します。 継承元のクラスのことを「スーパークラス」「親クラス」などと呼び、継承したクラスのことを「サブクラス」「子クラス」などと呼びます。親クラスを継承するためにはextendsを指定します。 ``` class 親クラス名 { 処理... } class 子クラス名 extends 親クラス名 { 処理... } ``` ### **● Javaにおける継承** –あるクラスの定義内容を受け継ぐこと –メソッド・フィールドを定義し直さなくてもそのまま使える <a href="https://i.loli.net/2020/03/22/mnWgBOFju5ehaPy.png" target="_blank"><img src="https://i.loli.net/2020/03/22/mnWgBOFju5ehaPy.png" width="40%"></a> ### **● Javaにおける継承** –継承したクラスで独自のメソッドやフィールドを追加することもできる (=拡張) –継承したクラスで元のメソッド・フィールドの定義を変更することもできる (=再定義・オーバーライド) <a href="https://i.loli.net/2020/03/22/SWgM4FuXNCcUnDP.png" target="_blank"><img src="https://i.loli.net/2020/03/22/SWgM4FuXNCcUnDP.png" width="40%"></a> <br> ## **1.継承の作成** クラスの継承の例を以下に記載します。 #### **例** [JSample13_1A.java] ``` package JSample; class superclass { int i,j; void printij(){ System.out.println("i and j:" + i + " " + j); } } ``` [JSample13_1.java] ``` package JSample; class subclass extends superclass { int k; void printk() { System.out.println("k:" + k); } void printsum() { System.out.println("i + j + k:" + (i + j + k)); } } class JSample13_1 { public static void main(String[] args) { superclass superOb = new superclass(); subclass subOb = new subclass(); superOb.i = 10; superOb.j = 20; System.out.println("Contents of superOb: "); superOb.printij(); System.out.println(); subOb.i = 7; subOb.j = 8; subOb.k = 9; System.out.println("Contents of subOb: "); subOb.printij(); subOb.printk(); System.out.println(); System.out.println("Sum of i,j and k in subOb:"); subOb.printsum(); } } ``` #### **実行結果** Contents of superOb: <br> i and j:10 20<br> <br> Contents of subOb: <br> i and j:7 8<br> k:9<br> <br> Sum of i,j and k in subOb:<br> i + j + k:24 <br><br> ## **2.コンストラクタの呼び出し規則** 「親クラス」と「子クラス」のコンストラクタは次の規則で呼び出されます。 * 「子クラス」のインスタンス生成時、まず「親クラス」のコンストラクタが呼ばれ、その後「子クラス」のコンストラクタが呼ばれる。 * 「親クラス」の呼ばれるコンストラクタは、引数がない「コンストラクタ名()」が呼び出される。 * もし、「親クラス」に引数があるコンストラクタしかない場合は、「親クラス」に引数なしのコンストラクタを作成して、そこから引数有りのコンストラクタを呼び出すようにするか、または「子クラス」から「super(引数リスト);」で明示的に呼び出す必要があります。 #### **例** [JSample13_2.java] ``` package JSample; class Parent132 { public String ps1 = "親クラスのメンバ変数が参照されました。"; public Parent132() { System.out.println("親クラスのコンストラクタ(引数なし)が呼ばれました。"); } public void pm() { System.out.println("親クラスのメソッドが呼ばれました。"); } } class Child132 extends Parent132 { // Parentクラス(親クラス)を継承。 public String cs1 = "子クラスのメンバ変数が参照されました。"; public Child132() { System.out.println("自クラスのコンストラクタ(引数なし)が呼ばれました。"); } public void cm() { System.out.println("子クラスのメソッドが呼ばれました。"); } } public class JSample13_2 { public static void main(String[] args) { Child132 child = new Child132(); // 子クラスのインスタンスを生成。 System.out.println(child.ps1); // 親クラスのメンバ変数を参照。 System.out.println(child.cs1); // 子クラスのメンバ変数を参照。 child.pm(); // 親クラスのメソッドの呼び出し。 child.cm(); // 子クラスのメソッドの呼び出し。 } } ``` #### **実行結果** 親クラスのコンストラクタ(引数なし)が呼ばれました。<br> 自クラスのコンストラクタ(引数なし)が呼ばれました。<br> 親クラスのメンバ変数が参照されました。<br> 子クラスのメンバ変数が参照されました。<br> 親クラスのメソッドが呼ばれました。<br> 子クラスのメソッドが呼ばれました。 <br><br> ## **3.this変数** this変数は、呼び出されたコンストラクタやメソッドのオブジェクトを参照するために使われる予約語(keyword)である。 ``` class Person { String name; void printName() { System.out.println(this.name); } void whatIsYourName() { this.printName(); } } ``` <br><br> ## **4.super変数** superとは、Javaにおけるサブクラスでオーバーライド(親クラスのメソッドを子クラスで継承)された変数やインスタンスを参照する場合に使用されます。 つまり、子クラスのインスタンス(new [クラス名()]で作られたクラスの実体のこと)から、親クラスのインスタンスのメンバにアクセスして、値を参照する必要があるときにsuperが使用されます。 #### **例** [JSample13_3.java] ``` package JSample; class SuperClassSample { String str = "SuperClass"; public String getSrt() { return str; } } class SubClassSample extends SuperClassSample { String str = "SubClass"; public String getSrt() { return str; } public void print() { System.out.println("super.str = " + super.str); System.out.println("str = " + str); System.out.println("super.getSrt() = " + super.getSrt()); System.out.println("getSrt() = " + getSrt()); } } public class JSample13_3 { public static void main(String[] args) { SubClassSample scs = new SubClassSample(); scs.print(); } } ``` #### **実行結果** super.str = SuperClass<br> str = SubClass<br> super.getSrt() = SuperClass<br> getSrt() = SubClass <br><br> ## **5.メソッドのオーバーライド** クラスを継承した時に元になっているスーパークラスで定義されているメソッドを継承したサブクラスにて同じメソッド名(と同じ引数)で書き換えることが出来ます。つまり上書きするということです。これをメソッドのオーバーライドと言います。 具体的な例で考えてみます。スーパークラスとしてクラスAを用意し、クラスAを継承したクラスB1、クラスB2があったとします。スーパークラスであるクラスAには「show」というメソッドが定義されています。ここでクラスB1で「show」というメソッドをオーバーライドしてみます。 #### **例** [JSample13_4.java] ``` package JSample; class A { public void show() { System.out.println("super classのprint メソッド!"); } } class B1 extends A { public void show() { System.out.println("sub classのprint メソッド!"); } } class B2 extends A { } class JSample13_4 { public static void main(String args[]) { B1 b1 = new B1(); b1.show(); B2 b2 = new B2(); b2.show(); } } ``` #### **実行結果** sub classのprint メソッド!<br> super classのprint メソッド! <br><br> ## **6.メソッドのオーバーロード** メソッドを引数を付けて呼び出す時、引数に記述する値のデータ型はメソッドで決められたものしか指定できません。その為、同じような機能を持つメソッドであっても引数のデータ型が異なれば別々のメソッドを用意する必要があります。 Javaでは引数のデータ型や引数の数が完全に一致していなければ異なるメソッドに同じメソッド名を付けることが出来ます。 #### **例** [JSample13_5.java] ``` package JSample; class JSample13_5 { public static void main(String args[]) { System.out.println(plus(10, 7)); System.out.println(plus(3.2, 4)); System.out.println(plus(7, 1.223)); System.out.println(plus(5.08, 2.4)); } private static int plus(int n1, int n2) { System.out.println("int + int"); return n1 + n2; } private static double plus(int n1, double d1) { System.out.println("int + double"); return n1 + d1; } private static double plus(double d1, int n1) { System.out.println("double + int"); return n1 + d1; } private static double plus(double d1, double d2) { System.out.println("double + double"); return d1 + d2; } } ``` #### **実行結果** int + int<br> 17<br> double + int<br> 7.2<br> int + double<br> 8.223<br> double + double<br> 7.48 <br><br> ## **7.final修飾子** javaのfinal修飾子はクラス、メソッド、変数全てにつけることができます。 <br> **・final変数** <br> 一度しか値を代入することができない変数をfinalを使うと宣言することができる。 ``` final float finalVariable = 3.14159f; ``` **※** finalVariable変数が定数になったため、再代入が禁止です。 <br> **・finalクラス** <br> クラスにfinalを付ける宣言することができる。そうすると、クラスを継承することができなくなる。 ``` final class FinalClass { } ``` extendsに続く部分にfinalクラスが書いてあると、コンパイルエラーになる。 ``` class SubclassOfFinalClass extends FinalClass { } ``` **※** コンパイル結果:final FinalClassからは継承できません <br> **・finalメソッド** <br> メソッドにfinalを付けて宣言することができる。メソッドにfinalを付けると、サブクラスでメソッドをオーバーライドできなくなる。 ``` class SuperMethod { final void superMethod() { } } ``` サブクラスでメソッドをオーバーライドすると,コンパイルエラーになる。 ``` class SubclassOfSuperMethod extends SuperMethod { final void superMethod() { } } ``` **※** コンパイル結果:SubclassOfSuperMethodのSuperMethod()はSuperMethodのsuperMethod()をオーバーライドできません <br> #### **例** 円の面積を求めるクラスを使って、円の面積を求めている。 [JSample13_6.java] ``` package JSample; class Circle { final double PI = 3.14159;//final変数PIの宣言、初期化 final double getAreaOfCircle(double radius) {//finalメソッド宣言 return PI * radius * radius;//円の面積 } } public class JSample13_6 { public static void main(String[] args) { Circle circle = new Circle();//Circleクラスのオブジェクト作成 double area = circle.getAreaOfCircle(2.0);//半径2.0の面積 System.out.println("area = " + area); } } ```
content
戻る