0Pricing
Swift Academy · レッスン

プロトコルベースの抽象化

具象型ではなくプロトコルに依存します。

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

プロトコルベースの抽象化

具体的な型ではなくプロトコルを注入すると、実装を自由に差し替えられます。利用側が依存するのはクラスではなく、その振る舞いだけです。

プロトコルの定義

機能をプロトコルとして記述します。準拠する型であれば、どれでも依存関係として渡せます。

protocol Logging {
    func log(_ message: String)
}
print("Protocol describes behavior, not a concrete class.")

具体的な型を準拠させる

実際の実装をプロトコルに準拠させます。これが本番用の依存関係になります。

protocol Logging { func log(_ m: String) }
struct ConsoleLogger: Logging {
    func log(_ m: String) { print("LOG: \(m)") }
}
ConsoleLogger().log("ready")

プロトコルへの依存

利用側のプロパティ型をプロトコルにすることで、準拠する任意の値を受け入れられます。

protocol Logging { func log(_ m: String) }
struct ConsoleLogger: Logging { func log(_ m: String) { print(m) } }
struct Service {
    let logger: Logging // protocol, not ConsoleLogger
    func run() { logger.log("running") }
}
Service(logger: ConsoleLogger()).run()

実装の差し替え

型がプロトコルであるため、利用側に触れずに、別の準拠実装を渡せます。

protocol Logging { func log(_ m: String) }
struct Loud: Logging { func log(_ m: String) { print(m.uppercased()) } }
struct Quiet: Logging { func log(_ m: String) {} }
struct Service { let logger: Logging; func run() { logger.log("hi") } }
Service(logger: Loud()).run()
Service(logger: Quiet()).run()

インターフェースに対するプログラミング

これは「具象ではなく抽象に依存する」という原則です。高レベルのコードは、低レベルの詳細から隔離されます。

protocol Storage { func save(_ v: Int) }
struct MemoryStore: Storage { func save(_ v: Int) { print("kept \(v)") } }
struct Manager { let store: Storage; func add() { store.save(1) } }
Manager(store: MemoryStore()).add()

複数の準拠型

複数の型が同じプロトコルに準拠でき、それぞれネットワーク、ディスク、メモリなどの状況に適した実装になります。

protocol Source { func value() -> Int }
struct Fixed: Source { func value() -> Int { 10 } }
struct Doubler: Source { func value() -> Int { 20 } }
func use(_ s: Source) { print(s.value()) }
use(Fixed())
use(Doubler())

関連する振る舞いを持つプロトコル

プロトコルには複数のメソッドを宣言でき、依存関係に対する明確な契約を形成できます。

protocol Cache {
    func get(_ key: String) -> Int?
    func set(_ key: String, _ v: Int)
}
struct Dict: Cache {
    var store: [String: Int] = [:]
    func get(_ k: String) -> Int? { store[k] }
    mutating func set(_ k: String, _ v: Int) { store[k] = v }
}
var c = Dict(); c.set("a", 1)
print(c.get("a") ?? -1)

ジェネリック制約

プロトコルに制約されたジェネリックパラメータを介して注入することもでき、existentialによるオーバーヘッドを避けられます。

protocol Greeter { func greet() -> String }
struct English: Greeter { func greet() -> String { "Hello" } }
struct Welcome<G: Greeter> {
    let greeter: G
    func show() { print(greeter.greet()) }
}
Welcome(greeter: English()).show()

安定した契約

プロトコルが安定している限り、実装内部を変更しても利用側を壊さずに済みます。

protocol Formatter { func format(_ n: Int) -> String }
struct Plain: Formatter { func format(_ n: Int) -> String { "\(n)" } }
struct Padded: Formatter { func format(_ n: Int) -> String { String(format: "%03d", n) } }
func render(_ f: Formatter) { print(f.format(7)) }
render(Plain())
render(Padded())

モックの準備

重要なのは、プロトコルによって、テストで実際の実装の代わりに偽の準拠型を提供できることです。次のレッスンでは、これを詳しく扱います。

protocol Network { func fetch() -> String }
struct Real: Network { func fetch() -> String { "server data" } }
struct VM { let net: Network; func load() { print(net.fetch()) } }
VM(net: Real()).load()

確認問題

具体的なクラスではなくプロトコル型を注入するのはなぜですか。

まとめ

プロトコルを注入すると具体的な型を抽象化できるため、準拠する任意の型に置き換えられます。これは「抽象に依存する」という原則に沿っており、代替実装、そして特にテストダブルを利用できるようにします。次は、テストで依存関係をモックします。

よくある質問

「プロトコルベースの抽象化」レッスンは無料ですか?

はい。「プロトコルベースの抽象化」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと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に戻る