本記事は下記記事を読めば理解できるので原文を読もう。
昼間、夜に読んで具体的な利用ケースが思い浮かばなかった。忘れそうなので記事に残す。
開発環境
> swift --version swift-driver version: 1.45.2 Apple Swift version 5.6 (swiftlang-5.6.0.323.62 clang-1316.0.20.8) Target: x86_64-apple-macosx12.0 > xcodebuild -version Xcode 13.3 Build version 13E113
モチベーション
プロトコルのデフォルト実装あたりを見ていたら、Controlling extension points in protocols – Hacking with Swift を教えてもらったので読んだ。
コード1
protocol Dog { func bark() } extension Dog { func bark() { print("ワン!") } } struct JapaneseDog: Dog {} struct AmericanDog: Dog { func bark() { print("bow!") } } let dogs: [Dog] = [JapaneseDog(), AmericanDog()] for dog in dogs { dog.bark() } // ワン! // bow!
プロトコル Dog
の bark()
のデフォルト実装がextension内で宣言されている。
JapaneseDog
はデフォルト実装の bark()
が実行され、AmericanDog
は bark()
をオーバライドしたものが実行される。ここまでは理解できる。
コード2
protocol Dog { // func bark() } extension Dog { func bark() { print("ワン!") } } struct JapaneseDog: Dog {} struct AmericanDog: Dog { func bark() { print("bow!") } } let dogs: [Dog] = [JapaneseDog(), AmericanDog()] for dog in dogs { dog.bark() } // ワン! // ワン!
プロトコルからメソッドの定義を除外すると、オーバーライドよりデフォルト実装が優先される。(そういう仕様だよと言われればそうなんだけど、直感に反する)
いつ使うねん?感がある。開発における具体的な利用ケースが思いつかない。デフォルト実装の利用を強制(= オーバーライドさせない)させたい時に使うと言われればそうなのだが、オーバーライド自体は宣言できてしまうのでスッキリしない。SwiftLintで吸収できれば良いかなと思ったけどそこまでやるかなあみたいな気持ちになった。