post Image
Swiftクイズ: extension Arrayでオーバーロードされたメソッドを呼び分ける

次のようなコードがあります。

protocol P {}
struct S: P {}

extension Array {
    func hoge() -> String { return "Any" } // ①
}
extension Array where Element == S {
    func hoge() -> String { return "Equal" } // ②
}
extension Array where Element: P {
    func hoge() -> String { return "Protocol" } // ③
}
extension Array where Element == P {
    func hoge() -> String { return "Existence" } // ④
}

問題 1

次のコードで呼ばれるのは、メソッド①〜④のどれでしょうか?

[S()].hoge()

問題 2 〜 4

それでは、残りの3つのメソッドを呼び分けるにはどうしたら良いでしょうか?
各々1行から2行のコードで回答してください。


thinking time! ⏱

解答

解答 1

[S()].hoge()

上記のコードで呼ばれるのは…

extension Array {
    func hoge() -> String { return "Any" } // ①
}
extension Array where Element == S {
    func hoge() -> String { return "Equal" } // ②
}
extension Array where Element: P {
    func hoge() -> String { return "Protocol" } // ③
}
extension Array where Element == P {
    func hoge() -> String { return "Existence" } // ④
}

のうち、②でした。
本記事のコードを

swift -frontend -typecheck -debug-constraints hoge.swift

に掛けてみると、解決のログが確認できました。
ログによると [S()].hoge().hoge() は ② <Element where Element == S> (Array<Element>) -> () -> Int の引数側と

Constraint restrictions:
  Array<S> to Array<S> is [deep equality]

という関係であるため、他の(サブタイプ関係の)オーバーロードよりも優先的に選ばれたようです。

なお、Swift実装の詳細について @ukitaka さんにご助言いただきました。ありがとうございました。

debug-constraintsの出力みてみると、オーバーロードのどの候補を使うかの比較自体はこの辺りでやってそうな雰囲気ありますね
https://github.com/apple/swift/blob/master/lib/Sema/CSRanking.cpp#L387-L725

解答 2 〜 4

オーバーロードされたメソッド①〜④それぞれを呼び分けるコードは、以下の通りです。

extension Array {
    func hoge() -> String { return "Any" } 
}

[S() as Any].hoge() // "Any"

解説:
extension Array に whereが省略されている場合、 where Element: Any と解釈される。
その証拠に extension Array where Element: Anyhoge() を実装しようとすると redeclaration だって怒られます。
image.png

extension Array where Element == S {
    func hoge() -> String { return "Equal" } 
}

[S()].hoge() // "Equal"

解説:
解答1のとおり。
== S は「S 型(のサブタイプ)である」という意味。

extension Array where Element: P {
    func hoge() -> String { return "Protocol" }
}

func f<T: P>(_ t: T) -> String { return [t].hoge() }
f(S()) // "Protocol"

解説:
: P は「P プロトコルに適合している」という意味。
Pプロトコルとして見てほしければジェネリックな関数を通す(全称量化する)。
詳しくは https://github.com/apple/swift/blob/master/docs/TypeChecker.rst#polymorphic-types

extension Array where Element == P {
    func hoge() -> String { return "Existence" }
}

[S() as P].hoge() // "Existence"

解説:
== P は「Pプロトコルの存在型(のサブタイプ)である」という意味。
存在型については 型システムの理論からみるSwiftの存在型(Existential Type) – Qiitaを参照して下さい。

as P したときには、存在型にパッケージングされる(これを存在量化という)。
存在型Pは、Pプロトコルには適合しない。
詳しい理屈は Swiftでprotocol型の値がそのprotocol自身にconformしていない理由 – Qiita を参照してください。


『 Swift 』Article List
Category List

Eye Catch Image
Read More

Androidに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

AWSに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Bitcoinに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

CentOSに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

dockerに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

GitHubに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Goに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Javaに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

JavaScriptに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Laravelに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Pythonに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Rubyに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Scalaに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Swiftに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Unityに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Vue.jsに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Wordpressに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

機械学習に関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。