为什么非可选的Any可以保持nil? [英] Why non optional Any can hold nil?

查看:215
本文介绍了为什么非可选的Any可以保持nil?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Swift中,我可以声明类型为Any的常量,并在其中放入String.

In Swift I can declare a constant of type Any and put a String into it.

let any: Any = "hello world"

好.另一方面,我不能nil值放入any,因为它不是可选的.

Good. On the other hand I cannot put a nil value into any because it's not optional.

let any: Any = nil

error: nil cannot initialize specified type 'Any' (aka 'protocol<>')
let any: Any = nil
              ^

完美.但是为什么编译器允许我编写以下代码?

Perfect. But why does the compiler allow me do write the following code?

let couldBeNil: String? = nil
let any: Any = couldBeNil
print(any) // nil

Any是否不遵循Swift规则,即只能用nil填充可选的var/let?

Doesn't Any follow the Swift rule that only an Optional var/let can be populated with nil?

在Xcode Playground 7.2 + Swift 2.1.1中进行了测试

Tested with Xcode Playground 7.2 + Swift 2.1.1

推荐答案

TL; DR; 编译器将swift中的可选内容翻译为Optional枚举实例,并且由于Any可以映射设置为任意值,可用于存储可选内容.

TL;DR; Optionals in swift are translated by the compiler to Optional enum instances, and since Any can map to any value, it can be used to store optionals.

Swift如何表示可选内容?通过将SomeType?映射到Optional枚举的具体实现来实现:

How does Swift represent optionals? It does it by mapping SomeType? to a concrete implementation of the Optional enum:

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.

Now, a variable of type Any is able to hold an enum value (or any other kind of value, or even metatype information), so it should be able to hold for example a nil String, aka String?.none, aka Optional<String>.none.

让我们看看会发生什么.正如我们在Optional声明中看到的,nil对应于所有类型的.none枚举大小写:

Let's see what happens, though. As we see by the Optional declaration, nil corresponds to the .none enum case for all types:

nil == Optional<String>.none // true
nil == Optional<Int>.none    // true
[Double]?.none == nil        // also true

因此,从理论上讲,您应该能够将nil分配给声明为Any的变量.尽管如此,编译器仍不允许这样做.

So theoretically, you should be able to assign nil to a variable declared as Any. Still, the compiler doesn't allow this.

但是为什么编译器不让您将nil分配给Any变量?这是因为它无法推断映射.none枚举大小写的类型. Optional是一个通用枚举,因此它需要一些内容来填充T通用参数,而普通的nil太宽了.应该使用哪个.none值?来自Int的一个,来自String的一个,另一个??

But why doesn't the compiler let you assign nil to an Any variable? It's because it can't infer to which type to map the .none enum case. Optional is a generic enum, thus it needs something to fill the T generic parameter, and plain nil is too broad. Which .none value should it use? The one from Int, the one from String, another one?

这会给出一条支持以上段落的错误消息:

This gives an error message supporting the above paragraph:

let nilAny: Any = nil // error: nil cannot initialize specified type 'Any' (aka 'protocol<>')

以下代码有效,并且等效于分配nil:

The following code works, and is equivalent to assigning a nil:

let nilAny: Any = Optional<Int>.none

,因为上面的Any变量实际上保存了Optional枚举的有效值.

, as the above Any variable is actually holding a valid value of the Optional enum.

间接分配也起作用,因为nil在后台被转换为Optional<Type>.none.

Indirect assignments work too, as behind the scenes nil is converted to 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.我们可以认为该关键字提供了糖语法.

Unlike other languages, in Swift nil corresponds to a concrete value. But it needs a type to work with, for the compiler to know which Optional<T>.none it should allocate. We can think of the keyword as providing sugar syntax.

这篇关于为什么非可选的Any可以保持nil?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆