準拠する型がメソッドおよびプロパティの実装を持つようにプロトコルを拡張することができます。これにより、型ごとに個別に、あるいはグローバル関数にではなく、プロトコル自体に振る舞いを定義することができます。

例えば、RandomNumberGenerator プロトコルが、ランダムな Bool 値を返す必須の random() メソッドの結果を使用する randomBool() メソッドを提供するように拡張することができます。

extension RandomNumberGenerator {
    func randomBool() -> Bool {
        return random() > 0.5
    }
}

プロトコルにエクステンションを生成することで、追加で変更することなく、準拠する型すべてが自動的にこのメソッド実装を獲得します。

let generator = LinearCongruentialGenerator()
print("Here's a random number: \(generator.random())")
// "Here's a random number: 0.37464991998171" と出力
print("And here's a random Boolean: \(generator.randomBool())")
// "And here's a random Boolean: true" と出力

デフォルト実装を提供

プロトコルのメソッド要件やプロパティ要件にデフォルト実装を提供するために、プロトコルエクステンションを使用することができます。準拠する型が必須のメソッドやプロパティの独自の実装を提供している場合は、その実装がエクステンションによって提供される実装の代わりに使用されます。

NOTE
エクステンションによって提供されるデフォルト実装を持つプロトコル要件は、オプショナルプロトコル要件とはまったく異なります。準拠する型がどちらの実装も提供する必要はありませんが、デフォルト実装を持つ要件は、オプショナルチェーンせずに呼び出すことができます。

例えば、TextRepresentable プロトコルを継承する PrettyTextRepresentable プロトコルは、単に textualDescription プロパティにアクセスして結果を返す、必須の prettyTextualDescription プロパティのデフォルト実装を提供することができます。

extension PrettyTextRepresentable  {
    var prettyTextualDescription: String {
        return textualDescription
    }
}

プロトコルエクステンションに制約を追加

プロトコルエクステンションを定義するとき、エクステンションのメソッドやプロパティが利用できるようになる前に、準拠する型が満たす必要がある制約を指定することができます。Where Clauses で説明されているように、where 節で拡張するプロトコルの名前の後に制約を記述します。

例えば、コレクションの要素が TextRepresentable プロトコルに準拠することを適用する CollectionType プロトコルに、エクステンションを定義することができます。

extension CollectionType where Generator.Element: TextRepresentable {
    var textualDescription: String {
        let itemsAsText = self.map { $0.textualDescription }
        return "[" + itemsAsText.joinWithSeparator(", ") + "]"
    }
}

textualDescription は、コレクション内の各要素のテキスト表現をカンマ区切りのリストに連結して角括弧で囲った、コレクション全体の説明テキストを返します。

TextRepresentable プロトコルに準拠する構造体 Hamster と、Hamster 値の配列について考えてみます。

let murrayTheHamster = Hamster(name: "Murray")
let morganTheHamster = Hamster(name: "Morgan")
let mauriceTheHamster = Hamster(name: "Maurice")
let hamsters = [murrayTheHamster, morganTheHamster, mauriceTheHamster]

Array は CollectionType に準拠し、配列の要素は TextRepresentable プロトコルに準拠しているため、配列内の内容のテキスト表現を取得するために textualDescription プロパティを使用することができます。

print(hamsters.textualDescription)
// "[A hamster named Murray, A hamster named Morgan, A hamster named Maurice]" と出力
NOTE
準拠する型が、同じメソッドやプロパティの実装を提供する複数の制約エクステンションの要件を満たす場合、Swift は最も特殊な制約に対応している実装を使用します。

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.