■継承とは
継承とは既存のクラスの機能を引き継いで自分のクラスの機能として扱うモノです
つまり複数のクラスを作るとき同じ記述をするのは面倒なので共通項目だけを1つクラスで用意してそれを引き継ぐことでほかのクラスはそれぞれの特有の機能を持たせることで記述を簡略化できます。
この記事では 継承関係を明確にするために
継承元のクラス:スーパークラス
継承するクラス:サブクラス
と表記します
■基本文法
継承のルールは
・継承できるクラスは1つまで
・サブクラスのコンストラクタは必ずスーパークラスを呼び出す
・サブクラスはデフォルトコンストラクターを許さない
・宣言 public class サブクラス名 extends スーパークラス名{}
・コンストラクタ public サブクラス(){
super();
}
*注意
コンストラクターはスーパークラスに存在しない場合は上記のようにしなくても自由に記述できますが、
もしスーパークラスにコンストラクターがある場合次の手順で処理しないとオブジェクト生成時に永久ループに入りコンパイラエラーになる
①スーパークラスのコンストラクターの読み込み
②サブクラスのコンストラクターの読み込み
③オブジェクトの呼び出し
①→②→③の順番を守るために上記のようにコンストラクターの1行目でsuper();のようにスーパークラスのコンストラクタ呼び出しを記述する必要がある。
新しいクラスを用意するときコンストラクターを用意するのは今度継承で使う可能性を考慮することで
コンストラクター名(){}を必ず記述すればsuper()でとりあえずスーパークラスの中身を見なくても問題なく動作できる
■superとthis
ところで上記にある「super」やカプセル化で散々でてきた「this」は一見オブジェクト変数のような振る舞いだが実際どういうモンわかり図らいの表にまとめてみた
意味 | 意味 | ||
---|---|---|---|
super | スーパークラスのオブジェクト | this | このクラスのオブジェクト |
super() | スーパークラスのコンストラクター | this() | 自クラスのコンストラクター |
少し補足すると「this()」もスーパークラス同様、1行目で呼び出さないとコンパイラエラーになる
1つのクラスでたくさんコンストラクタを作ってコンストラクタ間で互いに呼び出す場合このルールを守れば、
引数の数が一致しない場合に初期値を追加して再び呼び出すことも可能
■継承例
円の面積・円錐と球のそれぞれの体積を求めるプログラムを用意しました(入力操作は前回のKeyInputクラスを使用)
public class Circle {/*スーパークラス*/
int r;
public Circle(int r) { this.r = r; }
public double Menseki() { return (r * r * Math.PI); }
}
public class Corne extendes Circle{ /*円錐*/
int height ;
public Corne(int r, int height){ super(r); this.height = height; }
public double Taiseki() {return ( ( menseki() * height) / 3); }
}
public class Boll extends Circle{ /*球*/
public Boll(int r) { super(r); }
public double Taiseki() {return ( (4 * menseki() * r) / 3 ); }
}
public class Calc {
/*メイン処理*/
public static void main(String [] ag) {
System.out.print("半径を入力してください>");
int r = KeyInput.intInput();
Circle cs = new Circle(r);
Cone cv = new Cone(r,5);
Boll bv = new Boll(r) ;
System.out.println("半径\t" + r + "の場合");
System.out.println("円の面積は " + cs.Menseki() + "㎡で、");
System.out.println("高さ 5mの円錐の体積は " + cv.Taiseki() + "㎥で,);
System.out.println("球の体積は " + bv.Taiseki() + "㎥になります");
}
}
int r;
public Circle(int r) { this.r = r; }
public double Menseki() { return (r * r * Math.PI); }
}
public class Corne extendes Circle{ /*円錐*/
int height ;
public Corne(int r, int height){ super(r); this.height = height; }
public double Taiseki() {return ( ( menseki() * height) / 3); }
}
public class Boll extends Circle{ /*球*/
public Boll(int r) { super(r); }
public double Taiseki() {return ( (4 * menseki() * r) / 3 ); }
}
public class Calc {
/*メイン処理*/
public static void main(String [] ag) {
System.out.print("半径を入力してください>");
int r = KeyInput.intInput();
Circle cs = new Circle(r);
Cone cv = new Cone(r,5);
Boll bv = new Boll(r) ;
System.out.println("半径\t" + r + "の場合");
System.out.println("円の面積は " + cs.Menseki() + "㎡で、");
System.out.println("高さ 5mの円錐の体積は " + cv.Taiseki() + "㎥で,);
System.out.println("球の体積は " + bv.Taiseki() + "㎥になります");
}
}
--------------
†実行結果†
--------------
半径を入力してください>14
半径 14の場合
円の面積は615.44㎡
高さ5メートルの円錐の体積は1025.733㎥
球の体積は11488.2133㎥になります
--------------
球の体積の公式:半径×半径×半径×円周率×(4/3) *()内は分数
今回の継承の目的は
体積と面積の公式の違いを利用して 面積×高さ を表現するときに面積の処理だけスーパークラスで処理して残りを各自違う計算で求めています。
CircleオブジェクトにあるMenseki()を自分のもののようにほかの2つのクラスが利用できるところが利点です。
■利用価値
スーパークラスに足りないものが追加できるというのが継承だが基本的には役割が同系統になるのが望ましい
ではどんなケースが継承しやすいかというとJava APIの中の「awt」「swing」パッケージにあるGUI部品クラス(ButtonやLabel)をつかうと
GUIアプリが作れるがプログラムによっては足りない機能があるかもしれない。
このときGUI部品を継承すればゲームを作るときとかの判定処理につかえるかも
球の体積の公式:半径×半径×半径×円周率×(4/3) *()内は分数
今回の継承の目的は
体積と面積の公式の違いを利用して 面積×高さ を表現するときに面積の処理だけスーパークラスで処理して残りを各自違う計算で求めています。
CircleオブジェクトにあるMenseki()を自分のもののようにほかの2つのクラスが利用できるところが利点です。
■利用価値
スーパークラスに足りないものが追加できるというのが継承だが基本的には役割が同系統になるのが望ましい
ではどんなケースが継承しやすいかというとJava APIの中の「awt」「swing」パッケージにあるGUI部品クラス(ButtonやLabel)をつかうと
GUIアプリが作れるがプログラムによっては足りない機能があるかもしれない。
このときGUI部品を継承すればゲームを作るときとかの判定処理につかえるかも