0Pricing
Swift Academy · レッスン

エクステンションでのデフォルト実装

プロトコルエクステンションで共通の振る舞いを提供します。

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

問題点

プロトコルは要件を宣言しますが、動作は提供しません。準拠するすべての型で同じロジックを繰り返す必要があると、コードが重複してしまいます。プロトコル拡張を使うとデフォルト実装を提供でき、この問題を解決できます。

protocol Greeter {
    func greet() -> String
}

デフォルトの追加

プロトコルの拡張で要件を実装できます。準拠する型は、独自の実装で上書きしない限り、その動作をそのまま利用できます。

protocol Greeter { func greet() -> String }

extension Greeter {
    func greet() -> String { "Hello!" }
}

struct Robot: Greeter {}
print(Robot().greet())

デフォルトの上書き

準拠する型は独自の実装を提供でき、その実装が拡張のデフォルトより優先されます。

protocol Greeter { func greet() -> String }
extension Greeter { func greet() -> String { "Hello!" } }

struct French: Greeter {
    func greet() -> String { "Bonjour!" }
}
print(French().greet())

追加メソッドの提供

拡張では、プロトコルにまったく含まれていない新しいメソッドも追加できます。準拠するすべての型が自動的にそれらを利用できるようになります。

protocol Named { var name: String { get } }

extension Named {
    func loudName() -> String { name.uppercased() }
}

struct City: Named { let name: String }
print(City(name: "paris").loudName())

デフォルトの計算プロパティ

拡張では、計算プロパティもデフォルトとして提供できます。

protocol Sized {
    var width: Double { get }
    var height: Double { get }
}

extension Sized {
    var area: Double { width * height }
}

struct Rect: Sized { let width: Double; let height: Double }
print(Rect(width: 2, height: 5).area)

要件を利用した構築

デフォルト実装では、プロトコル自身の要件を呼び出せます。これにより、各型が提供すべき最小限の契約から、より豊かな動作を組み立てられます。

protocol Summable {
    var values: [Int] { get }
}

extension Summable {
    var total: Int { values.reduce(0, +) }
}

struct Cart: Summable { let values: [Int] }
print(Cart(values: [10, 20, 30]).total)

制約付き拡張

where句を使うと、追加の条件を満たす場合にだけデフォルトを適用できます。ここでは、SelfがEquatableでもある場合にだけデフォルトが存在します。

protocol Container {
    associatedtype Item
    var items: [Item] { get }
}

extension Container where Item: Equatable {
    func contains(_ x: Item) -> Bool { items.contains(x) }
}

struct Bag: Container { let items: [Int] }
print(Bag(items: [1, 2, 3]).contains(2))

デフォルトと要件の同時定義

プロトコルでメソッドを宣言し、同時にデフォルト実装を提供できます。プロトコルにメソッドを列挙すると、プロトコル型を介した動的ディスパッチが可能になります。

protocol Logger {
    func log() -> String
}
extension Logger {
    func log() -> String { "default log" }
}

struct A: Logger {}
struct B: Logger { func log() -> String { "B log" } }

let loggers: [Logger] = [A(), B()]
for l in loggers { print(l.log()) }

静的ディスパッチの注意点

メソッドが拡張にのみ存在し、プロトコルには存在しない場合、プロトコル型の値を介した呼び出しでは、具体的な型が独自の実装を定義していても拡張側のバージョンが使われます。動的ディスパッチを行うには、メソッドをプロトコルで宣言します。

protocol P {}
extension P { func who() -> String { "P-default" } }
struct Q: P { func who() -> String { "Q" } }

let direct = Q()
let asP: P = Q()
print(direct.who())
print(asP.who())

定型コードの削減

小さな必須インターフェースと豊富なデフォルト実装の組み合わせが、プロトコル指向設計の中心です。準拠する型は最小限だけを実装し、共有する動作は1か所に置けます。

protocol Identifiable { var id: Int { get } }
extension Identifiable {
    var tag: String { "ID-" + String(id) }
}
struct Order: Identifiable { let id: Int }
print(Order(id: 7).tag)

複数の拡張の組み合わせ

整理しやすくするために、デフォルト実装を複数の拡張に分割できます。それらはすべて準拠する型に反映されます。

protocol Money { var cents: Int { get } }
extension Money { var dollars: Double { Double(cents) / 100 } }
extension Money { var label: String { "$" + String(format: "%.2f", dollars) } }

struct Price: Money { let cents: Int }
print(Price(cents: 1299).label)

確認問題

プロトコル拡張のデフォルト実装についての理解を確認します。

まとめ

プロトコル拡張はデフォルト実装を提供し、準拠する型が共有された動作を継承し、必要に応じて上書きできるようにします。追加メソッドや計算プロパティを提供したり、whereでデフォルトに制約を付けたりできます。また、静的ディスパッチと動的ディスパッチの規則として、動的ディスパッチを行うメソッドはプロトコルで宣言する必要があることも学びました。

よくある質問

「エクステンションでのデフォルト実装」レッスンは無料ですか?

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

「エクステンションでのデフォルト実装」で何を学びますか?

プロトコルエクステンションで共通の振る舞いを提供します。 ブラウザで直接実行するハンズオンコードでSwift Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

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

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

「エクステンションでのデフォルト実装」レッスンにはどのくらい時間がかかりますか?

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

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

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

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

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