0Pricing
Swift Academy · レッスン

プロトコル合成

&で複数のプロトコル要件を組み合わせます。

「プロトコル合成」はCoddyKit上の無料Swift Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはSwift Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Swift Academyコースには全4レッスンが含まれています。

プロトコルの組み合わせ

1つの値が複数のプロトコルに同時に準拠しなければならない場合があります。Swiftでは、&演算子を使ってプロトコルを組み合わせられます。SomeProtocol & AnotherProtocolのように記述します。

protocol Named { var name: String { get } }
protocol Aged { var age: Int { get } }

組み合わせたパラメーター

Named & Aged型のパラメーターは、両方のプロトコルに準拠する任意の値を受け取れます。

protocol Named { var name: String { get } }
protocol Aged { var age: Int { get } }

struct Person: Named, Aged {
    let name: String
    let age: Int
}

func intro(_ x: Named & Aged) {
    print(x.name + " is " + String(x.age))
}
intro(Person(name: "Sam", age: 28))

継承ではいけない理由

組み合わせを使うと、新しい統合プロトコルを作成せずに、呼び出し側で両方のプロトコルを要求できます。プロトコルを小さく再利用しやすく保てます。

protocol Drawable { func draw() -> String }
protocol Resizable { func resize(_ f: Double) -> String }

struct Icon: Drawable, Resizable {
    func draw() -> String { "drawing" }
    func resize(_ f: Double) -> String { "x" + String(f) }
}

func render(_ v: Drawable & Resizable) {
    print(v.draw(), v.resize(2))
}
render(Icon())

3つ以上の組み合わせ

必要な数だけ&演算子を追加して、プロトコルを連結できます。

protocol A { func a() -> String }
protocol B { func b() -> String }
protocol C { func c() -> String }

struct X: A, B, C {
    func a() -> String { "a" }
    func b() -> String { "b" }
    func c() -> String { "c" }
}

func use(_ v: A & B & C) { print(v.a(), v.b(), v.c()) }
use(X())

クラスとの組み合わせ

クラス型とプロトコルを組み合わせることもできます。SomeClass & SomeProtocolとすると、その値がそのクラスまたはサブクラスであり、かつプロトコルに準拠していることを要求します。

class Vehicle { var speed = 0 }
protocol Electric { var battery: Int { get } }

class Tesla: Vehicle, Electric { var battery = 100 }

func check(_ v: Vehicle & Electric) {
    print(v.speed, v.battery)
}
check(Tesla())

組み合わせた型の返却

関数は組み合わせた型を返せます。これにより、結果が列挙されたすべてのプロトコルに準拠することを呼び出し元に保証できます。

protocol Named { var name: String { get } }
protocol Aged { var age: Int { get } }
struct Person: Named, Aged { let name: String; let age: Int }

func makePerson() -> Named & Aged {
    Person(name: "Eve", age: 22)
}
let p = makePerson()
print(p.name, p.age)

組み合わせのtypealias

typealiasを使って組み合わせに読みやすい名前を付けると、&の連鎖を繰り返さずに再利用できます。

protocol Codable2 { func encode() -> String }
protocol Loggable { func log() -> String }

typealias Persistable = Codable2 & Loggable

struct Record: Persistable {
    func encode() -> String { "data" }
    func log() -> String { "logged" }
}
func save(_ r: Persistable) { print(r.encode(), r.log()) }
save(Record())

コレクションでの組み合わせ

組み合わせた型の値を配列に格納し、各要素で、すべてのプロトコルのメンバーにアクセスできます。

protocol Named { var name: String { get } }
protocol Aged { var age: Int { get } }
struct P: Named, Aged { let name: String; let age: Int }

let group: [Named & Aged] = [P(name: "A", age: 1), P(name: "B", age: 2)]
for g in group { print(g.name, g.age) }

標準プロトコルとの組み合わせ

組み合わせは、ライブラリのプロトコルと使うと特に効果的です。たとえば、CustomStringConvertibleとEquatableの両方を要求できます。

func report<T>(_ items: [T]) where T: CustomStringConvertible & Equatable {
    for i in items { print(i.description) }
}
report([1, 2, 3])

空のプロトコルをマーカーとして使う

合成を使うと、マーカープロトコル(要件なし)と機能を持つプロトコルを組み合わせて、型システム上で意図を表現できます。

protocol Secure {}
protocol Sendable2 { func send() -> String }

struct Packet: Secure, Sendable2 {
    func send() -> String { "sent securely" }
}
func transmit(_ p: Secure & Sendable2) { print(p.send()) }
transmit(Packet())

合成とジェネリクスの違い

合成(A & B)では具体的な型が消去されますが、ジェネリクス(<T: A & B>)では保持されます。パラメーターと戻り値の型を関連付ける必要がある場合は、ジェネリクスを使用します。

protocol A { func a() -> String }
protocol B { func b() -> String }
struct S: A, B { func a() -> String { "a" }; func b() -> String { "b" } }

func generic<T: A & B>(_ x: T) -> T { print(x.a(), x.b()); return x }
_ = generic(S())

理解度チェック

プロトコル合成についての理解度を確認しましょう。

まとめ

&を使ったプロトコル合成では、新しい結合プロトコルを定義せずに、複数のプロトコル(および必要に応じて1つのクラス)への適合を一度に要求できます。合成にはtypealiasで名前を付けられ、パラメーター、戻り値、コレクションで使用できます。また、具体的な型の保持に関して、合成とジェネリクスがどのように異なるかも確認しました。

よくある質問

「プロトコル合成」レッスンは無料ですか?

はい。「プロトコル合成」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Swift Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Swift Academyコースには全4レッスンが含まれています。

「プロトコル合成」で何を学びますか?

&で複数のプロトコル要件を組み合わせます。 ブラウザで直接実行するハンズオンコードでSwift Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Swift Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのSwift Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。

「プロトコル合成」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このSwift Academyレッスンでコードを書いて実行できますか?

はい。すべてのSwift Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. 契約としてのプロトコル
  2. エクステンションでのデフォルト実装
  3. プロトコル合成
  4. 条件付き適合
← Swift Academyに戻る