斯威夫特 5.1。考虑以下。
let x: Any? = nil
let y: Any = x
print("x \(x)") // x nil
print("type(of: x) \(type(of: x))") // type(of: x) Optional<Any>
print("x == nil \(x == nil)") // x == nil true
print("y \(y)") // y nil
print("type(of: y) \(type(of: y))") // type(of: y) Optional<Any>
print("y == nil \(y == nil)") // y == nil false
Run Code Online (Sandbox Code Playgroud)
我们有两个变量,设置为相同的东西——nil。他们打印相同,他们的类型打印相同 - 但一个== nil和另一个没有。
Any,人们怎么会发现它实际上为零?想想Any并Optional<Wrapped>喜欢盒子。
Any是一个不透明的盒子,可以装任何东西。您可以通过尝试使用as?.Optional<Wrapped>是一个透明的盒子。它可以让你看到它的内容均是一个价值Optional<Wrapped>.some(wrapped)或Optional<Wrapped>.none()。AnOptional<Any>和Any包含 anOptional<Wrapped>不是一回事。
x是 的值Optional<Any>.none,也就是nil。nil被打印出来,所以这是有道理的。
type(of: x)是的类型x,Optional<Any>如我们的预期。
x == nil正在调用==类型为 的运算符(T, T) -> Bool。由于两个 args 都需要是相同的类型,并且x具有Optional<Any>.none(类型Optional<Any>)的值,nil因此推断为Optional<Any>.none。两者是等价的,所以我们得到了true,正如预期的那样。
y是一个类型的值Any。在编译时,对y. 恰巧隐藏在不透明窗帘背后的价值Any是x。print实现“透视” Any instances,向您展示真正存在的东西。
type(of: y)正在做类似的事情print。它使用运行时类型信息来准确查看存储的运行时值是什么y。yis的静态类型Any,但type(of: y)向我们展示了其值的运行时类型是Optional<Any>。
y == nil这是它变得有点棘手的地方。
选择调用哪个函数或运算符的重载是在编译时完成的,基于操作数的静态已知类型。也就是说,操作符和函数不是根据它们的参数类型动态调度的,而是基于它们的对象类型(例如fooin foo.bar())动态调度的。
此处选择的重载是==(lhs: Wrapped?, rhs: _OptionalNilComparisonType) -> Bool。您可以在 的第 449-481 行Optional.swift看到它的实现。
它的左侧操作数是Wrapped?,又名Optional<Wrapped>。
它的右侧操作数是_OptionalNilComparisonType。这是一种特殊类型,符合ExpressibleByNilLiteral.
Optional 是一种符合的类型ExpressibleByNilLiteral,这意味着您可以编写let x: Optional<Int> = nil,并且编译器可以使用该协议来理解nil应该意味着什么Optional<Int>.none。该ExpressibleByNilLiteral协议的存在允许此行为可以被其他类型扩展。例如,您可以想象一个 Python 互操作性框架,您希望能够在其中说let none: PyObject = nil, 可以传递到Python 的 null 类型Python并解析为None。
这里发生的事情是左侧(y, 类型Any)被提升为类型Any?。提升的值具有类型Optional<Any>.some(old_value_of_y)。右侧的nil用于实例化 的值_OptionalNilComparisonType,相当于调用_OptionalNilComparisonType.init(nilLiteral: ())。
因此,您的呼叫站点相当于:
Optional<Any>.some((Optional<Any>.none) as Any) == _OptionalNilComparisonType(nilLiteral: ()) /*
? ???_the value of x_?? ??
? ??_the value of y _________???
??_the value of y after promotion to optional__?? */
Run Code Online (Sandbox Code Playgroud)
根据实现,左侧是 a some,右侧是 a nil,因此它们是不相等的。
你可能会说:
嗯,这是非常不明显的行为,这不是我想要的。
我会回应:
不要忽略编译器错误,它们是正确的:
警告:比较型的非可选值
Any来nil总是返回false
| 归档时间: |
|
| 查看次数: |
217 次 |
| 最近记录: |