既存の型のソースコードにアクセスできない場合であっても、新しいプロトコルを採用し準拠するよう既存の型を拡張することができます。エクステンションで、既存の型に新しいプロパティやメソッド、サブスクリプトを追加することができ、プロトコルが要求するあらゆる要件を追加することができます。エクステンションについての詳細は、Extensions を確認してください。

NOTE
エクステンションでプロトコル準拠がインスタンスの型に追加された場合、型の既存のインスタンスは自動的にプロトコルを採用し準拠します。

例えば、このプロトコル TextRepresentable は、テキストで表現するための手段として、あらゆる型に実装することができます。それ自体の説明であり、現在の状態をテキストで表現します。

protocol TextRepresentable {
    var textualDescription: String { get }
}

前に見た Dice クラスが、TextRepresentable を採用し準拠するよう拡張することができます。

extension Dice: TextRepresentable {
    var textualDescription: String {
        return "A \(sides)-sided dice"
    }
}

このエクステンションは、Dice がオリジナルの実装としてプロトコルを持っているかのように、新しいプロトコルを採用します。 プロトコル名は型名の後にコロンで区切って記述し、エクステンションの波括弧内にすべてのプロトコル要件を実装します。

この時点で、すべての Dice インスタンスを TextRepresentable として扱うことができます。

let d12 = Dice(sides: 12, generator: LinearCongruentialGenerator())
print(d12.textualDescription)
// "A 12-sided dice" と出力

同様に、SnakesAndLadders ゲームクラスを TextRepresentable プロトコルを採用し準拠するよう拡張することができます。

extension SnakesAndLadders: TextRepresentable {
    var textualDescription: String {
        return "A game of Snakes and Ladders with \(finalSquare) squares"
    }
}
print(game.textualDescription)
// "A game of Snakes and Ladders with 25 squares" と出力

エクステンションでプロトコル採用を宣言

型があるプロトコルのすべての要件に準拠しているが、そのプロトコルを採用すると示していない場合、空のエクステンションでそのプロトコルを採用させることができます。

struct Hamster {
    var name: String
    var textualDescription: String {
        return "A hamster named \(name)"
    }
}
extension Hamster: TextRepresentable {}

この時点で、TextRepresentable 型が求められるところに Hamster のインスタンスを使用することができます。

let simonTheHamster = Hamster(name: "Simon")
let somethingTextRepresentable: TextRepresentable = simonTheHamster
print(somethingTextRepresentable.textualDescription)
// "A hamster named Simon" と出力
NOTE
プロトコルの要件を満たすだけでは、型が自動的にプロトコルを採用していることにはなりません。常にプロトコルの採用を明示的に宣言する必要があります。

Portions of this page are translations based on work created and shared by Apple and used according to terms described in the Creative Commons Attribution 4.0 International License.