カテゴリ: Swift 更新日: 2026/01/16

Swift Type ErasureでProtocolを使いやすく!初心者向け型消去の完全ガイド

Swift Type Erasure(型消去)でPATを使いやすくする
Swift Type Erasure(型消去)でPATを使いやすくする

先生と生徒の会話形式で理解しよう

生徒

「SwiftのProtocolを使うと便利って聞いたんですけど、難しい言葉が多くてよく分かりません。Type ErasureとかPATってなんですか?」

先生

「いい質問ですね。SwiftではProtocol(プロトコル)と呼ばれる“約束事”を使ってコードを整理できます。でも、Generics(ジェネリクス)を含むProtocol、つまりProtocol with Associated Type(PAT)はそのままでは使いにくいんです。その解決策がType Erasure(型消去)です。」

生徒

「型消去ってどういう意味ですか?」

先生

「難しく聞こえますが、ざっくり言えば“余計な型の情報を隠して、シンプルに扱えるようにする仕組み”です。たとえば、いろんな形のおもちゃを袋に入れて“おもちゃ”として扱うようなイメージですね。」

1. ProtocolとPATとは?

1. ProtocolとPATとは?
1. ProtocolとPATとは?

まずは基本から整理しましょう。SwiftのProtocolは「設計図」のようなものです。クラスや構造体に「この機能を必ず持ってね」と指示する仕組みです。

しかし、PAT(Protocol with Associated Type)と呼ばれるプロトコルは、型に依存する「関連型」を持っています。これは便利ですが、そのまま変数や配列にまとめて扱うことができません。

例えば、「データを入れ物にしまう」ようなプロトコルを考えてみます。


protocol Container {
    associatedtype Item
    func add(_ item: Item)
}

このようにassociatedtypeを使うと、「入れ物の中に入れる型」を後から自由に決められます。ただし、異なる型のContainerをひとまとめに管理するのは難しくなります。

2. なぜPATは使いにくいのか?

2. なぜPATは使いにくいのか?
2. なぜPATは使いにくいのか?

例えば、Containerを実装する構造体を2つ作ったとします。


struct IntBox: Container {
    func add(_ item: Int) { print("Intを追加: \(item)") }
}

struct StringBox: Container {
    func add(_ item: String) { print("Stringを追加: \(item)") }
}

ここで、両方のBoxを配列に入れてまとめて扱いたいと思っても、そのままではできません。理由は、Containerが「どんな型を扱うのか」が決まっていないからです。

つまり、PATは便利だけど「そのままでは配列や変数にできない」という欠点があるのです。

3. Type Erasure(型消去)の登場

3. Type Erasure(型消去)の登場
3. Type Erasure(型消去)の登場

ここで役に立つのがType Erasure(型消去)です。Type Erasureとは、具体的な型の情報を隠して、「とりあえずこのプロトコルを満たしているなら扱える」という形にする仕組みです。

身近な例で言えば、スーパーのレジ袋のようなものです。袋にリンゴやパンを入れても、外から見たら「袋」として同じように扱えます。

Swiftでは、この仕組みを作るために「ラッパー(包み紙)」となる構造体を作ります。


struct AnyContainer<T>: Container {
    private let _add: (T) -> Void
    
    init<C: Container>(_ container: C) where C.Item == T {
        self._add = container.add
    }
    
    func add(_ item: T) {
        _add(item)
    }
}

このAnyContainerは「どんな具体的なContainerでも包み込んで同じように扱える」仕組みになっています。これがType Erasureです。

4. 実際にType Erasureを使ってみよう

4. 実際にType Erasureを使ってみよう
4. 実際にType Erasureを使ってみよう

では、さきほどのIntBoxStringBoxをType Erasureでまとめてみましょう。


let intBox = IntBox()
let stringBox = StringBox()

let containers: [AnyContainer<Any>] = [
    AnyContainer(intBox as! Container),
    AnyContainer(stringBox as! Container)
]

// 共通の形式で扱える
containers.forEach { c in
    c.add("テスト") // 文字列も追加可能
}

このようにType Erasureを使うことで、「型が違うけど同じように扱いたい」というニーズに応えられます。

5. Type Erasureが使われる場面

5. Type Erasureが使われる場面
5. Type Erasureが使われる場面

Type ErasureはSwift標準ライブラリでも使われています。例えばAnySequenceAnyPublisherなどが代表例です。

これらは「中身がどんな型でも、とりあえずSequenceやPublisherとして扱える」ようにするための工夫です。初心者にとっては難しく見えますが、基本は「中身を隠して共通の顔にする」というシンプルな発想です。

日常の例えに置き換えると、「本、雑誌、漫画を全部まとめて“読み物”として本棚に並べる」と同じです。Type Erasureはまさにこの役割をSwiftの世界で担っています。

6. まとめると何が便利なのか?

6. まとめると何が便利なのか?
6. まとめると何が便利なのか?

初心者が最初に覚えておくべきポイントは以下です。

  • Protocolは「設計図」
  • PATは「型に依存する設計図」で便利だがそのままでは使いにくい
  • Type Erasureは「型の違いを隠して共通の顔にする仕組み」

つまり、Type Erasureを理解すればSwiftのProtocolやExtensionをもっと自由に活用できるようになります。

カテゴリの一覧へ
新着記事
New1
Go言語
Go言語のオブジェクト指向の特徴を完全ガイド!初心者でも理解できる他言語との違い
New2
Go言語
Go言語の条件分岐の見やすい書き方を徹底解説!初心者でもわかるif文の使い方
New3
Kotlin
Kotlinのクラス設計に役立つベストプラクティスまとめ|初心者でもわかるクラス設計の考え方
New4
Kotlin
Kotlinでアーキテクチャ設計の基本!MVC・MVP・MVVMの違いを解説
人気記事
No.1
Java&Spring記事人気No1
Go言語
Go言語の関数パラメータ!値渡しと参照渡しの違いを理解しよう
No.2
Java&Spring記事人気No2
Swift
Swift Playgroundの使い方を完全解説!初心者に最適な学習環境の始め方
No.3
Java&Spring記事人気No3
Swift
Swift開発環境の構築方法を徹底解説!Xcode・Windows・Linux対応
No.4
Java&Spring記事人気No4
Kotlin
Gradleファイル(build.gradle.kts)の書き方と役割をやさしく解説!Kotlin初心者向け完全ガイド
No.5
Java&Spring記事人気No5
Kotlin
Kotlinのインストール方法まとめ!Windows・Mac・Linux別にステップ解説
No.6
Java&Spring記事人気No6
Kotlin
Kotlinの演算子一覧と使い方!算術・比較・論理演算子の基本を解説
No.7
Java&Spring記事人気No7
Go言語
Go言語のWebアプリにおけるセキュリティベストプラクティス集
No.8
Java&Spring記事人気No8
Swift
Swiftのオプショナル型とは?初心者でもわかる使い方とアンラップの基礎