ページの作成
親となるページを選択してください。
親ページに紐づくページを子ページといいます。
例: 親=スポーツ, 子1=サッカー, 子2=野球
子ページを親ページとして更に子ページを作成することも可能です。
例: 親=サッカー, 子=サッカーのルール
親ページはいつでも変更することが可能なのでとりあえず作ってみましょう!
| この記事の要点 |
|
ポリモーフィズムとは
「多態性」「多様性」と訳される OOP の中心概念。同じ操作 (メソッド呼び出し) でも、対象の型によって異なる挙動になる性質。Java / PHP / Python など多くの言語で「オーバーライド」+「上位型での参照」で実現する。
古典例: 動物クラス
// 親クラス (抽象)
public abstract class Animal {
private String name;
public Animal(String name) { this.name = name; }
public String getName() { return name; }
public abstract String bark(); // サブクラスでオーバーライド
}
// 犬
public class Dog extends Animal {
public Dog(String name) { super(name); }
@Override
public String bark() { return "ワン!"; }
}
// 猫
public class Cat extends Animal {
public Cat(String name) { super(name); }
@Override
public String bark() { return "ニャー"; }
}
// 牛
public class Cow extends Animal {
public Cow(String name) { super(name); }
@Override
public String bark() { return "モー"; }
}
ポリモーフィズムが効くシーン
// ✅ Animal 型のリストに犬・猫・牛を混在させる
List<Animal> animals = new ArrayList<>();
animals.add(new Dog("ポチ"));
animals.add(new Cat("タマ"));
animals.add(new Cow("モモ"));
// 同じループで各々の鳴き声が出る
for (Animal a : animals) {
System.out.println(a.getName() + ": " + a.bark());
}
// → ポチ: ワン!
// タマ: ニャー
// モモ: モー
// 新しい動物 (Sheep) を追加してもループは無修正!
animals.add(new Sheep("ふわ")); // → ふわ: メェー
ポリモーフィズムが無い世界 (反面教師)
// ❌ ポリモーフィズム未使用: instanceof で分岐
public String bark(Object animal) {
if (animal instanceof Dog) {
return "ワン!";
} else if (animal instanceof Cat) {
return "ニャー";
} else if (animal instanceof Cow) {
return "モー";
}
// 動物が増えるたびに if が増える → OCP 違反
return "...";
}
// ✅ ポリモーフィズム使用: 呼ぶだけ
public String bark(Animal animal) {
return animal.bark(); // 1 行で済む
}
図形クラスでの例
public abstract class Shape {
public abstract double area();
public abstract double perimeter();
}
public class Circle extends Shape {
private double radius;
public Circle(double r) { this.radius = r; }
public double area() { return Math.PI * radius * radius; }
public double perimeter() { return 2 * Math.PI * radius; }
}
public class Rectangle extends Shape {
private double width, height;
public Rectangle(double w, double h) { this.width = w; this.height = h; }
public double area() { return width * height; }
public double perimeter() { return 2 * (width + height); }
}
public class Triangle extends Shape {
private double a, b, c;
public Triangle(double a, double b, double c) { this.a=a; this.b=b; this.c=c; }
public double area() {
double s = (a + b + c) / 2.0;
return Math.sqrt(s * (s-a) * (s-b) * (s-c));
}
public double perimeter() { return a + b + c; }
}
// 利用
List<Shape> shapes = List.of(
new Circle(5),
new Rectangle(3, 4),
new Triangle(3, 4, 5)
);
double totalArea = shapes.stream()
.mapToDouble(Shape::area)
.sum();
ファクトリパターンとの組み合わせ
// 文字列から動物を生成
public class AnimalFactory {
public static Animal create(String kind, String name) {
return switch (kind) {
case "dog" -> new Dog(name);
case "cat" -> new Cat(name);
case "cow" -> new Cow(name);
default -> throw new IllegalArgumentException(kind);
};
}
}
// 利用
String[] kinds = { "dog", "cat", "cow" };
List<Animal> animals = Arrays.stream(kinds)
.map(k -> AnimalFactory.create(k, "?"))
.toList();
animals.forEach(a -> System.out.println(a.bark()));
Strategy パターン (戦略パターン)
「アルゴリズムを差し替え可能にする」古典的なポリモーフィズム応用:
// 並び替え戦略
public interface SortStrategy<T> {
List<T> sort(List<T> list);
}
public class BubbleSort<T extends Comparable<T>> implements SortStrategy<T> {
public List<T> sort(List<T> list) { /* O(n^2) */ return ...; }
}
public class QuickSort<T extends Comparable<T>> implements SortStrategy<T> {
public List<T> sort(List<T> list) { /* O(n log n) */ return ...; }
}
public class MergeSort<T extends Comparable<T>> implements SortStrategy<T> {
public List<T> sort(List<T> list) { /* 安定 */ return ...; }
}
// 利用側はインターフェースだけ知っている
public class Sorter<T> {
private SortStrategy<T> strategy;
public Sorter(SortStrategy<T> s) { this.strategy = s; }
public List<T> doSort(List<T> list) { return strategy.sort(list); }
}
new Sorter<>(new QuickSort<>()).doSort(myList);
new Sorter<>(new MergeSort<>()).doSort(myList);
Template Method パターン
共通の流れだけ親クラスに書き、差分はサブクラスで上書き:
public abstract class ReportGenerator {
// テンプレートメソッド (確定アルゴリズム)
public final String generate() {
StringBuilder sb = new StringBuilder();
sb.append(header());
sb.append(body()); // ← サブクラスで実装
sb.append(footer());
return sb.toString();
}
protected String header() { return "===== レポート =====\n"; }
protected String footer() { return "==== ここまで ====\n"; }
protected abstract String body();
}
public class SalesReport extends ReportGenerator {
protected String body() { return "売上: 1,000,000円"; }
}
public class StockReport extends ReportGenerator {
protected String body() { return "在庫: 250 個"; }
}
new SalesReport().generate();
new StockReport().generate();
実務での効果
| シーン | ポリモーフィズム適用例 |
|---|---|
| 支払い方法 | カード / 銀行 / コンビニ → PaymentMethod#pay() |
| 通知 | Email / Slack / Push → Notifier#send() |
| エクスポート | CSV / Excel / PDF → Exporter#export() |
| 認証 | Local / OAuth / SAML → Authenticator#authenticate() |
| キャッシュ | Redis / Memcached / File → Cache#get() |
PHP での例
<?php
interface Notifier {
public function send(string $to, string $message): void;
}
class EmailNotifier implements Notifier {
public function send(string $to, string $message): void {
mail($to, '通知', $message);
}
}
class SlackNotifier implements Notifier {
public function send(string $to, string $message): void {
// POST to Slack Webhook
}
}
class LineNotifier implements Notifier {
public function send(string $to, string $message): void {
// POST to LINE Notify
}
}
// 利用側は具体クラスを知らない
function notifyAll(array $notifiers, string $to, string $msg): void {
foreach ($notifiers as $n) {
$n->send($to, $msg);
}
}
notifyAll([
new EmailNotifier(),
new SlackNotifier(),
new LineNotifier(),
], 'user@example.com', '緊急通知');
FAQ
Q: オーバーロード (引数違いの同名メソッド) もポリモーフィズム?
A: 厳密にはアドホック多相と呼ばれ別物。OOP で「ポリモーフィズム」と言えば通常はオーバーライドによるサブタイプ多相を指す。
Q: ポリモーフィズムを使うとパフォーマンスが落ちる?
A: 仮想メソッド呼び出しのコストは現代の JIT で誤差レベル。可読性・保守性のメリットが圧倒的に勝る。
Q: 関数型言語のポリモーフィズム?
A: パラメトリック多相 (ジェネリクス) + 型クラス (Haskell) / 高階関数で実現。OOP のサブタイプ多相とは別系統。
ページの作成
親となるページを選択してください。
親ページに紐づくページを子ページといいます。
例: 親=スポーツ, 子1=サッカー, 子2=野球
子ページを親ページとして更に子ページを作成することも可能です。
例: 親=サッカー, 子=サッカーのルール
親ページはいつでも変更することが可能なのでとりあえず作ってみましょう!
子ページ
子ページはありません
同階層のページ
人気ページ
- 1 Eclipseで「サーバーに追加または除去できるリソースがありません。」の原因と対処法
- 2 tomcat の起動 / 停止ログと catalina.log・catalina.out の違い
- 3 JavaScript base URL 取得方法|window.location.origin と SSR/Node.js 対応
- 4 YouTube Data API v3 エラー一覧|403/400/404 の主要原因と切り分け
- 5 Spring Frameworkのアノテーション一覧
- 6 Laravel エラー一覧|500/Blade/DB 接続/ルーティングの代表エラー
- 7 3Dグラフィックスとは|モデリング/レンダリング/主要ソフトウェア (Blender / Maya)
- 8 【Spring】@Valueアノテーションとは
- 9 CATALINA_HOME の確認方法 (Linux / Mac)
- 10 【Spring】@Autowiredアノテーションとは
最近更新/作成されたページ
- gRPCとは|仕組み・4つの通信方式・RESTとの違い 2026-06-12 15:50:39
- C++のcoutの使い方|コンソール出力と挿入演算子・書式指定 2026-06-12 15:50:19
- Google Search Consoleとは|主な機能と使い方・導入手順 2026-06-12 15:50:18
- MySQLのSTR_TO_DATEでnullが返る原因と対処|書式指定子の不一致 2026-06-12 15:50:18
- Pythonで実行時のパスを取得する方法|__file__・os.getcwd・pathlib 2026-06-12 15:50:18
- EC-CUBE3のディレクトリ構成と主要ファイル|本体・公開・設定の役割 2026-06-12 15:50:17
- pandasとは|PythonでDataFrameを使うデータ分析の基本 2026-06-12 15:50:17
- Linuxのheadコマンドの使い方|ファイル先頭の表示と行数・バイト指定 2026-06-12 15:50:17
- C/C++のprintfの使い方|書式指定子と幅・精度の指定 2026-06-12 15:50:16
- ラズベリーパイ(Raspberry Pi)とは|特徴・用途・始め方 2026-06-12 15:50:16
- C++の文法まとめ|変数・データ型・制御構文・配列・関数の基本 2026-06-12 15:50:15
- macOSでApacheを起動・停止・再起動する方法|apachectlとbrew services 2026-06-12 15:50:15
- Pythonで辞書(dict)の中身を確認する方法|keys・values・itemsの使い方 2026-06-12 15:50:15
- UE5のビルドとは|ライティング等の事前計算とパッケージ化の違い 2026-06-12 15:50:14
- UE5でHighResShotの保存画像のファイル名を取得する方法 2026-06-12 15:50:14
コメントを削除してもよろしいでしょうか?