導入
「すべての図形は面積を持つが、計算方法は図形ごとに違う」——このように共通の枠組みだけ決めて、中身は子に必ず実装させたいとき、abstract(抽象)クラスを使います。
図解
flowchart TB
A["abstract Shape<br/>abstract Area()<br/>(中身なし・実装を強制)"] --> C["Circle<br/>Area = πr²"]
A --> R["Rectangle<br/>Area = 幅×高さ"]
A -.->|new できない| X["Shape 単体では実体化不可"]
style A fill:#fff3e0
サンプル
Shape[] shapes = { new Rectangle(4, 3), new Circle(5) };
foreach (Shape s in shapes)
Console.WriteLine($"面積: {s.Area()}");
// 面積: 12 / 面積: 78.5...
// abstract: それ自体は new できず、子に実装を強制する
abstract class Shape
{
public abstract double Area(); // 中身なし。子が必ず実装する
}
class Rectangle : Shape
{
private int _w, _h;
public Rectangle(int w, int h) { _w = w; _h = h; }
public override double Area() => _w * _h;
}
class Circle : Shape
{
private double _r;
public Circle(double r) { _r = r; }
public override double Area() => 3.14159 * _r * _r;
}
abstract classはそれ自体をnewできない(設計の骨組み専用)abstractメソッドは中身を持たず、子クラスに実装を強制する- 「共通の枠組みは決めるが、実装は各自」という設計に使う
演習
Employee[] staff = { new FullTime(), new PartTime() };
foreach (var e in staff)
Console.WriteLine(e.Salary());
// TODO: abstract な Employee(abstract int Salary())を作り、
// FullTime(Salary → 300000)と PartTime(Salary → 120000)を定義してください
___
- 期待される出力:
300000120000(2行)
ヒント1を見る
abstract class Employee { public abstract int Salary(); }
ヒント2を見る
class FullTime : Employee { public override int Salary() => 300000; } class PartTime : Employee { public override int Salary() => 120000; }
まとめ
abstractクラスはnewできない設計の骨組みabstractメソッドは子に実装を強制する- 「枠組みは共通、実装は各自」を表現する
次回: 「できること」の契約だけを定める「インターフェース」です。