In Swift Any
型の定数を宣言し、それにString
を入れることができます。
let any: Any = "hello world"
良い。一方、I cannotはオプションではないため、nil
値をany
に入れます。
let any: Any = nil
error: nil cannot initialize specified type 'Any' (aka 'protocol<>')
let any: Any = nil
^
パーフェクト。しかし、コンパイラはなぜ次のコードを書くことを許可するのですか?
let couldBeNil: String? = nil
let any: Any = couldBeNil
print(any) // nil
Any
は、Swiftオプションのvar/letにのみnil
を入力できるという規則に従っていませんか?
Xcode Playground 7.2でテスト済み+ Swift 2.1.1
TL; DR; Swiftのオプションは、コンパイラによってOptional
enumインスタンスに変換され、Any
は任意の値、オプションの保存に使用できます。
Swiftはオプションを表しますか?)SomeType?
をOptional
列挙型の具体的な実装にマッピングすることで行います。
Int? => Optional<Int>
String? => Optional<String>
Optional
の簡易宣言は次のようになります。
enum Optional<T> {
case none // nil
case some(T) // non-nil
}
これで、タイプAny
の変数は列挙値(またはその他の種類の値、またはメタタイプ情報)を保持できるため、たとえばnil
文字列を保持できるはずです。 、別名String?.none
、別名Optional<String>.none
。
しかし、何が起こるか見てみましょう。 Optional
宣言でわかるように、nil
はすべてのタイプの.none
enumケースに対応します。
nil == Optional<String>.none // true
nil == Optional<Int>.none // true
[Double]?.none == nil // also true
したがって、理論的には、nil
として宣言された変数にAny
を割り当てることができるはずです。それでも、コンパイラはこれを許可しません。
しかし、コンパイラがnil
をAny
変数に割り当てることができないのはなぜですか? .none
enumケースをマッピングするタイプを推測できないためです。 Optional
はジェネリック列挙型であるため、T
ジェネリックパラメーターを埋める何かが必要であり、プレーンnil
は広すぎます。どの.none
値を使用する必要がありますか? Int
からのもの、String
からのもの、別のもの?
これにより、上記の段落をサポートするエラーメッセージが表示されます。
let nilAny: Any = nil // error: nil cannot initialize specified type 'Any' (aka 'protocol<>')
次のコードは機能し、nil
を割り当てるのと同じです。
let nilAny: Any = Optional<Int>.none
、上記のAny
変数は実際にOptional
enumの有効な値を保持しているためです。
nil
がOptional<Type>.none
に変換されるため、間接的な割り当ても機能します。
var nilableBool: Bool? // nilableBool has the Optional<Bool>.none value
var nilBoolAsAny: Any = nilableBool // the compiler has all the needed type information from nilableBool
他の言語とは異なり、Swift nil
は具体的な値に対応します。ただし、コンパイラがどのOptional<T>.none
を割り当てる必要があるかを知るには、動作する型が必要です。キーワードは、砂糖の構文を提供するものと考えることができます。
Swift Docs: "Any
:すべてのタイプが暗黙的に準拠するプロトコル。"
すなわちtypealias Any = protocol<>
したがって、String?
、あなたはそれをOptional<String>
、 どこ Optional<T>
は次のように実装できます。
enum Optional<T> {
case Some(T), None
}
また、列挙型はタイプであるため、Any
プロトコルに準拠しています。コメントに記載されているように、nil
は型ではありません(したがって、Any
に準拠していません。値がありません(この場合、値には型がありません)。
オプションは言語に組み込まれ、通常の列挙型ではありませんが、Any
に準拠しているが、型のないnil
には準拠していないことは変わりません。
Any
にnil
が含まれているかどうかを確認する方法を探している人向け:
po value
を呼び出すと、Any
変数に値nil
が含まれていることが通知される場合、次の行はまだ機能しません。
if value == nil { ... } // Returns false and generates a warning
チェックする前に、まずAny
にDate
が含まれている可能性がある場合など、nillable値に変換する必要があります。
if Optional<Date>.none == value as? Date { ... } // Returns true and no warning
注:私はそれをテストしなかったので、保証はありませんが、次のように書かれた場合、上記の行も通過する可能性があります:
if Optional<Any>.none == value as? Any { ... }