在Swift中,我可以声明一个Any型常数,并在其中加上String.

let any: Any = "hello world"

好的另一方面,我cannotany中输入nil,因为它不是可选的.

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吗?

使用Xcodeplayground 7.2+Swift 2.1.1进行测试

推荐答案

编译器将swift中的TL;DR;个选项转换为Optional个枚举实例,由于Any可以映射到任何值,因此它可以用于存储选项.


Swift如何代表期权?它通过将SomeType?映射到Optional枚举的具体实现来实现:

Int? => Optional<Int>
String? => Optional<String>

Optional的简化声明如下所示:

enum Optional<T> {
    case none    // nil
    case some(T) // non-nil
}

现在,类型Any的变量能够保存枚举值(或任何其他类型的值,甚至元类型信息),因此它应该能够保存例如nil字符串,aka String?.none,aka Optional<String>.none.

让我们看看会发生什么.正如我们从Optional声明中看到的那样,nil对应于所有类型的.none枚举情况:

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

所以从理论上讲,你应该能够给一个声明为Any的变量赋值nil.不过,编译器不允许这样做.

为什么编译器不给Any赋值呢?这是因为它无法推断.none enum case 对应的类型.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枚举的有效值.

间接分配也起作用,因为幕后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.我们可以将关键字视为提供了sugar语法.

Swift相关问答推荐

是否有一个Kotlin等价的Swift s @ AddendableReport注释'

如何在visionOS中定制悬停效果区域

为SwiftUI文本视图提供固定宽度,并仅在文本换行时使文本视图底部增大

将NavigationSplitView更改为NavigationStack

将matchedGeometryEffect 应用于列表视图内的视图时,列表视图中的项目会受到影响 - SwiftUI

为什么我的 tableView 没有推送到 tableView 内的 detailViewController?

If 语句在 Swift 中有 2 个日期

如何从我的 macOS 应用程序打开 (.log) 文件?

Swift // Sprite Kit:类别位掩码限制

在 macOS (Swift) 上获取 BSD 驱动器名称的最佳方法是什么?

.onTapGesture 不适用于 Stepper,仅适用于其文本

如何在 SwiftUI 中实现 PageView?

更新我的 pod 导致 GoogleDataTransport Umbrella 标头出现错误

Swift 2 中的新 @convention(c):我该如何使用它?

3D touch /强制touch 实现

使用 DispatchTime.now() + float 延迟?

在 Swift 中以编程方式更新约束的常量属性?

在 xcode8 中找不到 ModuleName-Swift.h 文件

'类 'className' 的 NSManagedObject 必须具有有效的 NSEntityDescription.错误

我可以让#selector 引用 Swift 中的闭包吗?