一度に複数のプロトコルに準拠するよう型に要求することが有益な場合があります。プロトコルコンポジションで複数のプロトコルを 1 つの要件に結合することができます。プロトコルコンポジションは、protocol<SomeProtocol, AnotherProtocol> のような形式になります。山括弧 (<>) 内に必要なだけのプロトコルをカンマ区切りで列挙することができます。

次の例では、関数のパラメータで、2 つのプロトコル Named と Aged を 1 つのプロトコルコンポジション要件に結合しています。

protocol Named {
    var name: String { get }
}
protocol Aged {
    var age: Int { get }
}
struct Person: Named, Aged {
    var name: String
    var age: Int
}
func wishHappyBirthday(celebrator: protocol<Named, Aged>) {
    print("Happy birthday \(celebrator.name) - you're \(celebrator.age)!")
}
let birthdayPerson = Person(name: "Malcolm", age: 21)
wishHappyBirthday(birthdayPerson)
// "Happy birthday Malcolm - you're 21!" と出力

この例では、プロトコル Named の要件に gettable な String プロパティ name があります。また、gettable な Int プロパティ age の要件があるプロトコル Aged を定義しています。どちらのプロトコルも構造体 Person に採用されています。

また、パラメータ celebrator を受け取る関数 wishHappyBirthday を定義しています。このパラメータの型は protocol<Named, Aged> で、「Named と Aged の両プロトコルに準拠するあらゆる型」を意味しています。どちらのプロトコル要件にも準拠している限り、関数に渡される具体的な型については問題になりません。

そして、新しい Person インスタンス birthdayPerson を生成し、wishHappyBirthday(_:) 関数にこの新しいインスタンスを渡しています。Person は両プロトコルに準拠しているため、これは有効な呼び出しであり、wishHappyBirthday(_:) 関数は誕生日のお祝いを出力できています。

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.