言語
日本語
English

Caution

お使いのブラウザはJavaScriptが無効になっております。
当サイトでは検索などの処理にJavaScriptを使用しています。
より快適にご利用頂くため、JavaScriptを有効にしたうえで当サイトを閲覧することをお勧めいたします。

Swift辞典

  1. トップページ
  2. Swift辞典
  3. protocol のデフォルト実装 / プロトコル合成

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で多用されます。

記事の間違いや著作権の侵害等ございましたらお手数ですがまでご連絡頂ければ幸いです。