abstract で抽象クラス
中身の書きようがないのに、とりあえず 0 を返している
親クラスにメソッドを置くとき、親の段階では計算式が決まらないことがあります。従業員の月給は、正社員なら月額固定、アルバイトなら時給と勤務時間の掛け算で、「従業員」という親だけでは決めようがありません。
そこで仮に return 0; と書いておくと、2 つの困りごとが起きます。子で実装を書き忘れても黙って 0 が返ること、そして中身の無い new Employee() が作れてしまうことです。
本体を書かず、名前だけ決める
abstract を付けると、この 2 つがまとめて解決します。
Java
abstract class Employee {
private final String name;
protected Employee(String name) {
this.name = name;
}
// 本体を書かず、セミコロンで終える
public abstract int monthlyPay();
// 中身のあるメソッドも普通に置ける
public String describe() {
return name + " の月給は " + monthlyPay() + " 円";
}
}public abstract int monthlyPay(); は { } を持たず ; で終わります。「このメソッドは必ずあるが、中身は子が書く」という約束だけを置いた状態です。一方で describe() のような共通処理は親に書けますし、フィールドもコンストラクタも普通に持てます。
子は宿題を埋める側になります。
Java
class FullTimeEmployee extends Employee {
private final int monthly;
public FullTimeEmployee(String name, int monthly) {
super(name);
this.monthly = monthly;
}
@Override
public int monthlyPay() {
return monthly;
}
}書き忘れると FullTimeEmployee is not abstract and does not override abstract method monthlyPay() で止まります。実行するまで気づけなかったはずの抜けが、コンパイルの時点で出てくるようになりました。
new Employee(...) はもう作れない
abstract が付いたクラスは直接インスタンス化できません。new Employee("佐藤") と書くと Employee is abstract; cannot be instantiated になります。変数の型として使うのは自由なので、Employee e = new FullTimeEmployee("佐藤", 300000); の形で扱います。
子の側でまだ実装を決められないときは、その子自身も abstract にして、さらに下の世代へ宿題を回せます。
finalとabstractは同時に付けられません。finalは「これ以上継承させない」、abstractは「継承して埋めてもらう」で、意味が正反対だからです。
やってみよう
triangleArea(int base, int height) を完成させてください。
abstract class Shapeを定義し、public abstract int area();を宣言する。本体の{ }は付けませんTriangle extends Shapeを作り、コンストラクタでbaseとheightを受け取るTriangle側でarea()を実装し、base * height / 2を返すtriangleAreaの中でTriangleのインスタンスを作り、area()の結果を返す
int どうしの割り算なので、小数点以下は自動で切り捨てられます。7 と 3 なら 21 / 2 で 10 です。double にキャストしたくなりますが、ここは整数のまま素直に返してください。
要件
abstract class Shapeを定義し、abstract int area();を宣言すること (本体{ }は付けない)Triangle extends Shapeを定義し、@Overrideでarea()を実装してbase * height / 2を返すことSolution.triangleAreaの中でnew Triangle(base, height)を作り、そのarea()の戻り値を返すこと
入出力例
triangleArea(4, 5) → 10
triangleArea(0, 5) → 0
triangleArea(7, 3) → 10
triangleArea(10, 10) → 50
triangleArea(1, 1) → 0