ポリモーフィズム3日目のゴール
3日目のテーマは 「同じ命令で違う動き」 を “戦略として使う” ことです。
1日目:魔法のような「同じ命令で違う動き」を体験 2日目:if/switch を消して、使う側のコードをシンプルにする価値を理解
3日目は、さらに一歩進んで 「アプリの拡張性を最大化するために、ポリモーフィズムをどう使うか」 を学びます。
ここからが、オブジェクト指向の“本番”です。
ポリモーフィズムは「未来の変更」を見据えた設計
追加・変更が来ても、使う側のコードを変えないための仕組み
アプリ開発では必ずこういう未来が来ます。
新しい通知方法を追加したい 新しい支払い方法を追加したい 新しい図形を描画したい 新しいレポート形式を追加したい
このとき、 使う側のコードを一切変えずに済む設計 ができているかどうかが、 “中級者”と“上級者”の分かれ目です。
ポリモーフィズムは、 そのための最強の武器です。
例題:NotificationService を「未来に強い」設計にする
新しい通知方法が増えても、サービス側は変えない
まず、共通の親型。
public abstract class Notification {
public abstract void send();
}
Javaメール通知。
public class MailNotification extends Notification {
@Override
public void send() {
System.out.println("メール送信");
}
}
Javaプッシュ通知。
public class PushNotification extends Notification {
@Override
public void send() {
System.out.println("プッシュ通知送信");
}
}
JavaSMS通知。
public class SmsNotification extends Notification {
@Override
public void send() {
System.out.println("SMS送信");
}
}
Javaサービス側はこう。
public class NotificationService {
public void sendAll(List<Notification> list) {
for (Notification n : list) {
n.send();
}
}
}
Javaここで重要なのは、 NotificationService は通知の種類を一切知らない ということです。
新しい通知方法(LINE通知など)を追加しても、
public class LineNotification extends Notification {
@Override
public void send() {
System.out.println("LINE通知送信");
}
}
Javaサービス側は変わりません。
n.send();
Javaこの「未来の変更に強い」構造こそ、 ポリモーフィズムの真価です。
重要ポイントの深掘り:ポリモーフィズムは「分岐の未来」を消す
if/switch を使うと未来が地獄になる
初心者がよく書くコードはこうです。
if (type.equals("mail")) {
// メール送信
} else if (type.equals("push")) {
// プッシュ送信
} else if (type.equals("sms")) {
// SMS送信
}
Java新しい通知方法が増えるたびに if が増える switch が増える メソッドが肥大化する
未来が地獄です。
ポリモーフィズムならこう。
n.send();
Java新しい通知方法が増えても 使う側は永遠に変わらない。
未来の分岐を消す設計 これがポリモーフィズムの本質です。
例題:図形アプリで「未来の追加」に強い設計を体験する
Shape の draw() が図形ごとに違う動きをする
共通の親型。
public abstract class Shape {
public abstract void draw();
}
Java円。
public class Circle extends Shape {
@Override
public void draw() {
System.out.println("○ を描画");
}
}
Java四角。
public class Square extends Shape {
@Override
public void draw() {
System.out.println("□ を描画");
}
}
Java三角。
public class Triangle extends Shape {
@Override
public void draw() {
System.out.println("△ を描画");
}
}
Java使う側はこう。
public void drawAll(List<Shape> shapes) {
for (Shape s : shapes) {
s.draw();
}
}
Java新しい図形「星」を追加しても、
public class Star extends Shape {
@Override
public void draw() {
System.out.println("★ を描画");
}
}
Java使う側は変わりません。
s.draw();
Java未来の追加に強い設計ができている ということです。
重要ポイントの深掘り:ポリモーフィズムは「オープン・クローズド原則」を満たす
変更には閉じて、拡張には開いている設計
オブジェクト指向の重要な原則に オープン・クローズド原則(OCP) があります。
クラスは「拡張に対して開いて」 「変更に対して閉じて」いなければならない。
つまり、
新しい種類を追加できる(拡張に開いている) 既存のコードを変更しなくていい(変更に閉じている)
という設計が理想です。
ポリモーフィズムは、 この原則を自然に満たします。
新しい通知方法を追加できる 新しい図形を追加できる 新しい支払い方法を追加できる
でも、使う側のコードは変わらない。
これが、 ポリモーフィズム=OCPを満たす設計 ということです。
例題:支払いアプリで「未来の追加」を想定した設計
Payable の pay() が支払い方法ごとに違う動きをする
共通インターフェース。
public interface Payable {
void pay(int amount);
}
Javaクレジットカード。
public class CreditCardPayment implements Payable {
@Override
public void pay(int amount) {
System.out.println("クレジットカードで支払い");
}
}
Java銀行振込。
public class BankTransferPayment implements Payable {
@Override
public void pay(int amount) {
System.out.println("銀行振込で支払い");
}
}
Java使う側はこう。
public void payAll(List<Payable> list) {
for (Payable p : list) {
p.pay(1000);
}
}
Java新しい支払い方法(PayPayなど)を追加しても、
public class PayPayPayment implements Payable {
@Override
public void pay(int amount) {
System.out.println("PayPayで支払い");
}
}
Java使う側は変わりません。
p.pay(1000);
Javaこれが、 未来の追加に強い設計=ポリモーフィズムの力 です。
3日目の実践:「未来の追加」を妄想して設計を見直す
自分のコードに対して、こう問いかけてみる
今日やってほしい練習は、 自分のアプリのコードに対して 次の問いを投げることです。
「新しい種類を追加するとき、 使う側のコードは変わらずに済むか?」
例えば、
新しい通知方法 新しい支払い方法 新しい図形 新しいレポート形式
を追加するとき、 使う側のコードが変わるなら、 ポリモーフィズムを使う余地があります。
逆に、 使う側が変わらないなら、 あなたの設計はすでに“未来に強い”です。
3日目で本当に掴んでほしいこと
ポリモーフィズム3日目で伝えたいのは、 「同じ命令で違う動き」は “未来の変更に強い設計”を作るための戦略である ということです。
種類を知らなくていい if/switch が消える 使う側のコードが永遠にシンプル 新しい種類を追加しても壊れない オープン・クローズド原則を満たす
これが、 ポリモーフィズムの真価です。
4日目以降は、 このポリモーフィズムを 「アプリ全体の構造」にどう活かすかを学んでいきます。


