導入
Open/Closed Principle——「拡張に対して開き、修正に対して閉じる」。新しい種類を追加するとき、既存のコードを書き換えずに足すだけで済む設計を目指します。
図解
flowchart TB
subgraph Before["修正に弱い"]
SW["if 種類==円 … else if 四角 …<br/>新種類のたびに if を書き換える"]
end
subgraph After["拡張に強い"]
I["interface Shape.Area()"]
I --> C["Circle"]
I --> R["Rectangle"]
I --> T["Triangle(足すだけ)"]
end
Before -->|多態性で置き換え| After
サンプル
// ✅ 新しい図形は「クラスを足すだけ」。合計処理は一切変更不要
IShape[] shapes = { new Circle(5), new Rectangle(4, 3) };
double total = shapes.Sum(s => s.Area());
Console.WriteLine($"合計面積: {total}");
interface IShape { double Area(); }
class Circle : IShape
{
private double _r;
public Circle(double r) { _r = r; }
public double Area() => 3.14159 * _r * _r;
}
class Rectangle : IShape
{
private int _w, _h;
public Rectangle(int w, int h) { _w = w; _h = h; }
public double Area() => _w * _h;
}
// Triangle を足したくなっても、上の合計処理は書き換え不要
- 新機能の追加が「既存コードの修正」ではなく「新クラスの追加」で済むようにする
- インターフェース+多態性がこの原則の主な実現手段
ifの羅列を増やし続ける設計は、この原則に反する
演習
IShape[] shapes = { new Square(4) };
Console.WriteLine(shapes.Sum(s => s.Area())); // 16
// TODO: IShape(Area())を実装する Square クラス(一辺 side)を定義してください
// (既存の合計処理を変えずに“足すだけ”で機能追加できることを体感)
interface IShape { double Area(); }
___
- 期待される出力:
16
ヒント1を見る
class Square : IShape { private int _s; public Square(int s) { _s = s; } public double Area() => _s * _s; }
ヒント2を見る
合計処理はIShapeに依存しているので、実装を足すだけで動きます
まとめ
- 開放閉鎖の原則:拡張に開き、修正に閉じる
- 新種類は「クラスを足すだけ」にする
- インターフェース+多態性が実現手段
次回: 親の代わりに使える「リスコフの置換原則」です。