Caution
お使いのブラウザはJavaScriptが実行できない状態になっております。
当サイトはWebプログラミングの情報サイトの為、
JavaScriptが実行できない環境では正しいコンテンツが提供出来ません。
JavaScriptが実行可能な状態でご閲覧頂くようお願い申し上げます。
protocol のデフォルト実装 / プロトコル合成
Swiftのprotocolにはデフォルト実装をextensionで追加でき、複数のprotocolを組み合わせる『プロトコル合成』や、型を抽象化する『any』『some』も活用できます。
構文
// プロトコルのデフォルト実装
extension プロトコル名 {
func メソッド名() { /* 実装 */ }
}
// プロトコル合成
func 関数名(引数: プロトコルA & プロトコルB) { }
// any(存在型)
var 変数名: any プロトコル名
// some(不透明型)
func 関数名() -> some プロトコル名 { }
構文一覧
| 構文 | 概要 |
|---|---|
| extension P { func f() {} } | プロトコルPにデフォルト実装を追加します。準拠する型で実装しなくても動作します。 |
| A & B | プロトコルAとBの両方に準拠することを要求するプロトコル合成です。 |
| any P | プロトコルPに準拠する任意の型を格納できる存在型です(Swift 5.7+)。 |
| some P | プロトコルPに準拠する特定の具体型を返す不透明型です。型の詳細を隠蔽します。 |
サンプルコード
protocol Greetable {
var name: String { get }
func greet() -> String
}
// デフォルト実装をextensionで追加
extension Greetable {
func greet() -> String {
return "こんにちは、\(name)です!"
}
}
protocol Farewell {
func farewell() -> String
}
struct Person: Greetable, Farewell {
var name: String
// greet()はデフォルト実装を使用
func farewell() -> String { "さようなら、\(name)でした!" }
}
// プロトコル合成
func introduce(_ x: Greetable & Farewell) {
print(x.greet())
print(x.farewell())
}
let p = Person(name: "花子")
introduce(p)
// any(存在型)
var anyone: any Greetable = Person(name: "次郎")
print(anyone.greet())
概要
protocolのデフォルト実装はextensionを使って提供します。準拠する型で同名メソッドを実装すれば上書きでき、実装しなければデフォルトが使われます。これによりコードの重複を大幅に減らせます。
プロトコル合成(『&』)は、複数のプロトコルを同時に要求する際に使います。継承とは異なり、クラス・構造体・列挙体のいずれでも利用できます。
『any』はSwift 5.7以降で型消去に使う存在型です。ボックス化のコストがあるため、パフォーマンスが重要な箇所では『some』や具体型の使用を検討してください。『some』は戻り値の型を隠蔽しつつコンパイラが具体型を把握できるため、SwiftUIで多用されます。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。