TL;DR
モジュール名.グローバル関数名
で呼び出せる。(標準のモジュール名はSwift
)
Swift.min(1, 2) // => 1
Foo.bar() // Note: Foo is framework
Swift 3.0 でのAPI名変更
Swift 3.0 では標準ライブラリのAPI名がガイドラインに沿って見直しがされました。
例えばSequenceType
の.minElement()
は.min()
へと変更されています。
これは大した話ではないと感じますが、以下のコードがコンパイルエラーになります。
extension Array {
func foo() {
let x = min(1, 2) // Compile error: Extra argument in call
print("x: \(x)")
}
}
上記はグローバル関数のmin()
を呼び出すつもりが、SequenceType.min()
が名前解決されてしまい、意図しない関数が呼び出されてしまっています。
このように名前空間が衝突した場合に、グローバル関数を明示的に呼び出すには以下のように頭にSwift.
を追加すればOKです。
extension Array {
func foo() {
let x = Swift.min(1, 2) // OK
print("x: \(x)")
}
}
同様に、Foo
モジュールのbar()
という関数を呼び出す場合には以下のようにすればOKです。
Foo.bar()
グローバル関数が重複した場合
さきほどの例ではArray
のextensionにおいて、SequenceType
の関数とグローバル関数の名前が衝突し、前者のほうが意図した呼び出しだと名前解決されました。
では、グローバル関数がモジュール間で重複した場合はどうなるのでしょうか?
(おそらく想像通りかと思いますが)結論から言えば、自身のモジュール内の関数が優先して名前解決されます。
// モジュール(プロジェクト)`Hello`に宣言されたグローバル関数
func bar() -> String {
return "bar in Hello"
}
// モジュール`Foo`に宣言されたグローバル関数
public func bar() -> String {
return "bar in Foo"
}
// `Hello`内でのコード
bar() // => bar in Hello
Hello.bar() // => bar in Hello
Foo.bar() // => bar in Foo
ここまで説明の都合上、グローバル関数を例に上げましたが、グローバル定数などのグローバルシンボルについても同様です。
let FOO_BAR: String = "FOO_BAR in Hello"
public let FOO_BAR: String = "FOO_BAR in Foo"
FOO_BAR // => FOO_BAR in Hello
Hello.FOO_BAR // => FOO_BAR in Hello
Foo.FOO_BAR // => FOO_BAR in Foo
まとめ
- 明示的にグローバルシンボルにアクセスする場合は
モジュール名.シンボル名
と書く - Swift標準のモジュール名は
Swift
- 名前解決は自身に近い位置から行われていく
蛇足
冒頭にあげたArray
のextensionのケースでコンパイルエラーになって「なんで?」って躓いたので、他にも躓く人がいるかもと思って書いてみました。