Java | 1 日 120 分 × 7 日アプリ学習 中級編:オブジェクト指向(OOP) - ポリモーフィズムアプリ

Web APP Java
スポンサーリンク
スポンサーリンク

ポリモーフィズム1日目のゴール

ポリモーフィズム(多態性)1日目のテーマは 「同じ命令で違う動き」 を体で理解することです。

継承アプリで学んだ「共通部分をまとめる」が、 “使う側のコードをシンプルにする” ところまで進化したのが ポリモーフィズムの世界です。

今日は、 「なぜ同じメソッド名で違う動きができるのか」 「それがどれほど強力なのか」 を、初心者でも直感で分かるように解説します。

ポリモーフィズムとは何か

同じメソッド呼び出しでも、実際に動く中身が変わる

ポリモーフィズム(polymorphism)は、 オブジェクト指向の中でも特に“魔法っぽい”機能です。

一言で言うと、

同じメソッド呼び出しでも、 実際に動く処理はオブジェクトの種類によって変わる。

これがポリモーフィズムです。

例えば、 animal.speak() と書いたとき、 その animal が犬なら「ワン!」 猫なら「ニャー」 鳥なら「ピヨ」 と、同じ命令なのに違う動き をします。

これがポリモーフィズムの本質です。

例題:Animal の speak() が“同じ命令で違う動き”を生む

親クラスと子クラスを使った最もシンプルな例

まず、親クラスを作ります。

public abstract class Animal {
    public abstract void speak();
}
Java

犬クラス。

public class Dog extends Animal {
    @Override
    public void speak() {
        System.out.println("ワン!");
    }
}
Java

猫クラス。

public class Cat extends Animal {
    @Override
    public void speak() {
        System.out.println("ニャー");
    }
}
Java

鳥クラス。

public class Bird extends Animal {
    @Override
    public void speak() {
        System.out.println("ピヨ");
    }
}
Java

ここまでで準備完了。 では、使う側のコードを見てください。

Animal a1 = new Dog();
Animal a2 = new Cat();
Animal a3 = new Bird();

a1.speak(); // ワン!
a2.speak(); // ニャー
a3.speak(); // ピヨ
Java

ここで起きていることは、

Animal 型として扱っているのに 実際には Dog / Cat / Bird の中身が動いている

ということです。

つまり、

「同じ命令(speak)で違う動き」 が実現しています。

重要ポイントの深掘り:なぜ同じ命令で違う動きができるのか

“型”ではなく“実体”がどのクラスかで動きが決まる

Java のポリモーフィズムは、 「変数の型」ではなく 「変数の中に入っている実体」 を見て動きます。

変数の型:Animal 実体:Dog / Cat / Bird

このとき、 a1.speak() を呼ぶときに Java はこう判断します。

「a1 の実体は Dog だから、Dog の speak() を呼ぶ」 「a2 の実体は Cat だから、Cat の speak() を呼ぶ」

つまり、

“どのクラスの実体が入っているか”で 実際に動くメソッドが決まる。

これがポリモーフィズムの仕組みです。

例題:通知アプリでポリモーフィズムを体感する

Notification の send() が種類ごとに違う動きをする

継承アプリで使った Notification を思い出しましょう。

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("プッシュ通知送信");
    }
}
Java

SMS通知。

public class SmsNotification extends Notification {
    @Override
    public void send() {
        System.out.println("SMS送信");
    }
}
Java

使う側はこう書くだけ。

List<Notification> list = List.of(
    new MailNotification(),
    new PushNotification(),
    new SmsNotification()
);

for (Notification n : list) {
    n.send();
}
Java

ここで起きているのは、

同じ send() 呼び出し でも実際に動く処理は通知の種類によって違う

というポリモーフィズムです。

重要ポイントの深掘り:ポリモーフィズムが生む“使う側の自由”

「種類を意識しないコード」が書けるようになる

ポリモーフィズムの最大のメリットは、 使う側が種類を意識しなくてよくなる ことです。

例えば、通知を送るサービス。

public class NotificationService {
    public void sendAll(List<Notification> notifications) {
        for (Notification n : notifications) {
            n.send();
        }
    }
}
Java

ここでは、

メールか プッシュか SMSか

を一切気にしていません。

ただ send() を呼んでいるだけ。

種類ごとの違いは、 各クラスの中に閉じ込められている

これがポリモーフィズムの強さです。

例題:支払いアプリでポリモーフィズムを使う

Payable の pay() が支払い方法ごとに違う動きをする

支払い方法が複数あるアプリを考えます。

クレジットカード 銀行振込 電子マネー

まず、インターフェースを作ります。

public interface Payable {
    void pay(int amount);
}
Java

クレジットカード。

public class CreditCardPayment implements Payable {
    @Override
    public void pay(int amount) {
        System.out.println(amount + "円をクレジットカードで支払いました");
    }
}
Java

銀行振込。

public class BankTransferPayment implements Payable {
    @Override
    public void pay(int amount) {
        System.out.println(amount + "円を銀行振込で支払いました");
    }
}
Java

電子マネー。

public class EMoneyPayment implements Payable {
    @Override
    public void pay(int amount) {
        System.out.println(amount + "円を電子マネーで支払いました");
    }
}
Java

使う側はこう。

List<Payable> payments = List.of(
    new CreditCardPayment(),
    new BankTransferPayment(),
    new EMoneyPayment()
);

for (Payable p : payments) {
    p.pay(1000);
}
Java

ここでも、

同じ pay() 呼び出し でも実際の動きは支払い方法によって違う

というポリモーフィズムが働いています。

ポリモーフィズムの本質を一言で言うと

「違いはクラスの中に閉じ込める。使う側は同じ命令だけ使う。」

ポリモーフィズムの本質は、 この一文に集約できます。

違いはクラスの中に閉じ込める。 使う側は同じ命令だけ使う。

これによって、

使う側のコードがシンプルになる 種類が増えても使う側のコードは変わらない 変更に強い設計になる

というメリットが生まれます。

1日目の実践:「同じ命令で違う動き」を自分で作ってみる

3つのクラスを作って、同じメソッド名を持たせる

今日やってほしい練習は、とてもシンプルです。

  1. 親クラス(またはインターフェース)を作る
  2. 子クラスを3つ作る
  3. 同じメソッド名を持たせる
  4. List<親型> に入れてループで呼ぶ

例えば、

Shapedraw() Soundplay() Vehiclerun()

など、テーマは何でもOKです。

「同じ命令で違う動き」が 自分のコードで体感できれば、 ポリモーフィズムの理解は一気に深まります。

1日目で本当に掴んでほしいこと

ポリモーフィズム1日目で伝えたいのは、 「同じ命令で違う動き」がどれほど強力か という感覚です。

Animal の speak Notification の send Payable の pay

どれも、

使う側は同じ命令だけ使う 違いはクラスの中に閉じ込める 種類が増えても使う側は変わらない

という構造になっています。

これが、 オブジェクト指向の中でも最も美しい仕組みのひとつです。

2日目以降は、 このポリモーフィズムを 「設計の武器」として使う方法に踏み込んでいきます。

タイトルとURLをコピーしました