当前位置:  开发笔记 > IOS > 正文

为什么非可选任何可以保持零?

如何解决《为什么非可选任何可以保持零?》经验,为你挑选了2个好方法。

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

let any: Any = "hello world"

好.另一方面,我不能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规则只能填充一个Optional var/let nil吗?

使用Xcode Playground 7.2 + Swift 2.1.1进行测试

Cristik.. 66

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


Swift如何代表选项?它通过映射SomeType?Optional枚举的具体实现来实现:

Int? => Optional
String? => Optional

这样的简化声明Optional:

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

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

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

nil == Optional.none // true
nil == Optional.none    // true
[Double]?.none == nil        // also true

所以理论上,你应该能够分配nil一个声明为的变量Any.但是,编译器不允许这样做.

但为什么编译器不允许您分配nilAny变量?这是因为它无法推断映射.none枚举案例的类型.Optional是一个通用的枚举,因此它需要一些东西来填充T泛型参数,而朴素nil太宽泛.它.none应该使用哪个值?一个来自Int中,从一个String,另一个呢?

这给出了支持上段的错误消息:

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

以下代码有效,相当于分配nil:

let nilAny: Any = Optional.none

,因为上面的Any变量实际上是持有Optional枚举的有效值.

间接分配也可以,因为幕后nil转换为Optional.none.

var nilableBool: Bool? // nilableBool has the Optional.none value
var nilBoolAsAny: Any = nilableBool // the compiler has all the needed type information from nilableBool

与其他语言不同,Swift nil对应于具体的值.但它需要一种类型才能使用,以便编译器知道Optional.none应该分配哪种类型.我们可以将关键字视为提供糖语法.



1> Cristik..:

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


Swift如何代表选项?它通过映射SomeType?Optional枚举的具体实现来实现:

Int? => Optional
String? => Optional

这样的简化声明Optional:

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

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

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

nil == Optional.none // true
nil == Optional.none    // true
[Double]?.none == nil        // also true

所以理论上,你应该能够分配nil一个声明为的变量Any.但是,编译器不允许这样做.

但为什么编译器不允许您分配nilAny变量?这是因为它无法推断映射.none枚举案例的类型.Optional是一个通用的枚举,因此它需要一些东西来填充T泛型参数,而朴素nil太宽泛.它.none应该使用哪个值?一个来自Int中,从一个String,另一个呢?

这给出了支持上段的错误消息:

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

以下代码有效,相当于分配nil:

let nilAny: Any = Optional.none

,因为上面的Any变量实际上是持有Optional枚举的有效值.

间接分配也可以,因为幕后nil转换为Optional.none.

var nilableBool: Bool? // nilableBool has the Optional.none value
var nilBoolAsAny: Any = nilableBool // the compiler has all the needed type information from nilableBool

与其他语言不同,Swift nil对应于具体的值.但它需要一种类型才能使用,以便编译器知道Optional.none应该分配哪种类型.我们可以将关键字视为提供糖语法.


有趣.我猜这就是为什么我可以做`var x = 5`,但我不能做`var y = nil`,因为我得到一个错误:''nil'需要一个上下文类型`

2> Alex Popov..:

来自Swift Docs:" Any:所有类型都隐含符合的协议."

typealias Any = protocol<>

因此,当您声明时String?,您可以将其视为Optional,在哪里Optional可以实现为:

enum Optional {
  case Some(T), None
}

枚举是类型,因此它们符合Any协议.如评论中所述,nil不是类型(因此不符合Any,它是没有值(在这种情况下,没有值没有类型).

可选项被烘焙到语言中,并不是常规枚举,但它仍然表示它们符合,Any而无类型nil则不符合.

推荐阅读
谢谢巷议
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有