可选链接的动态类型与赋值不同
dynamicType of optional chaining not the same as assignment
可选链接returns总是一个可选值。
To reflect the fact that optional chaining can be called on a nil value, the result of an optional chaining call is always an optional value, even if the property, method, or subscript you are querying returns a nonoptional value.
为什么操场上的类型不是可选的?
let stringOptEmpty: String? = ""
stringOptEmpty?.isEmpty // is true
stringOptEmpty?.isEmpty.dynamicType // Bool.Type
但是下面的代码是
let isOk = stringOptEmpty?.isEmpty.dynamicType
isOk.dynamicType // Optional<Bool.Type>.Type
TLDR;
playground sidebar/column 将动态解析 playground 中的表达式,无论是分配给 variables (mutables/immutables) 的值还是只是 "free-floating"未赋值。
您的第一个示例将 dynamicType
应用于 值,它将解析为该特定值 的 类型(true.dynamicType
: Bool.Type
).
另一方面,您的第二个示例将 dynamicType
应用于 变量 (不可变,但我将使用 变量 与 value) 不同,后者必须具有具体类型,因此将解析为可以容纳任何类型的包装值的类型(true
或 false
) 以及 nil
(这里,nil
具体来说是 Optional<Bool.Type>.None
),无论变量实际持有什么值。因此,在您的第二个示例中,dynamicType
将解析为 Optional<Bool.Type>.Type
。
详情
playground中显示的值sidebar/column一般遵循以下显示规则:
对于赋值表达式,边栏中显示的值是分配的值,例如
var a = 4 // shows '4'
a = 2 // shows '2'
let b: () = (a = 3)
/* shows '()': the _value_ assigned to 'b', which is the _result_
of the assignment 'a = 3', to which a _side effect_ is that 'a'
is assigned the value '3'. */
对于不包含赋值的表达式,边栏中显示的值通常是表达式的结果,例如
true // shows 'true'
1 > 3 // shows 'false'
let c = 3
c // shows '3'
c.dynamicType // shows 'Int.Type'
在您的第一个示例(第 2-3 行)中,我们没有赋值,操场将在解析dynamicType
该值。由于我们正在处理可选值,value 要么只是包装类型的值(在本例中为 true
),要么值为 具体类型 .None
。即使游乐场显示例如let a: Int? = nil
的结果与边栏中的 nil
一样,显示的值实际上与说 let b: String = nil
[= 的 .None
(nil
) 不同62=]
- 对于
let a: Int? = nil
,a
的值实际上是Optional<Int.Type>.None
,
- 而对于
let b: String? = nil
,b
的 值 是 Optional<String.Type>.None
考虑到这一点,非nil
值 的解析 dynamicType
将是具体的 包裹 类型(在您的示例中,Bool.Type
自然是 true
的类型),而 nil
值的解析 dynamicType
将包括常规可选和包装的类型信息。
struct Foo {
let bar: Bool = true
}
var foo: Foo? = Foo()
/* .Some<T> case (non-nil) */
foo?.bar // true <-- _expression_ resolves to (results in) the _value_ 'true'
foo?.bar.dynamicType // Bool.Type <-- dynamic type of the _result of expression_
true.dynamicType // Bool.Type <-- compare with this
/* .None case (nil) */
foo = nil
foo?.bar.dynamicType // nil <-- _expression_ resolves to the _value_ 'Optional<Foo.Type>.None'
Optional<Foo.Type>.None.dynamicType
// Optional<Foo.Type>.Type <-- compare with this
现在,如果您将值赋值给一个变量,自然该变量必须具有具体类型。由于我们在运行时分配的值 可以是 .None
或 .Some<T>
,变量的类型必须是可以保存这两种情况的值的类型,因此, Optional<T.Type>
(不管变量是 nil
还是非 nil
值)。这是您在第二个示例中显示的情况:variable 的 dynamicType
(此处不可变,但使用 variable 不同于 value) isOk
是可以容纳 .None
和 .Some<T>
的类型,无论变量的实际值是什么,因此 dynamicType
解析为这种类型; Optional<Bool.Type>.Type
.
用括号包裹表达式可以逃避 Swift 游乐场的运行时自省?
有趣的是,如果表达式在应用 .dynamicType
之前用括号括起来,那么 playground 侧边栏会将包裹表达式的 .dynamicType
解析为 类型 的表达式,就好像它的实际值是未知的。例如,(...).dynamicType
中的 (...)
被视为具有具体类型的变量,而不是运行时解析的值。
/* .Some case (non-nil) */
foo?.bar // true
(foo?.bar).dynamicType /* Optional<Bool>.Type <-- as if (...)
is a _variable_ of unknown value */
/* .None case (nil) */
foo = nil
(foo?.bar).dynamicType /* Optional<Bool>.Type <-- as if (...)
is a _variable_ of unknown value */
我们可以进一步注意到,操场上任何用括号包裹的单独表达式都不会解析为任何东西(在侧边栏中)。如果用括号包裹表达式,就好像我们逃避了 sidebar:s 运行时自省(这可以解释为什么包裹在括号中的表达式的 dynamicType
会像 playground 无法使用这些表达式的运行时信息一样解析)
var a = 4 // shows '4'
(a = 2) // shows nothing; can't expand or get details in sidebar
老实说,我无法解释这是为什么,并将其归类为 Swift 游乐场的特点。
可选链接returns总是一个可选值。
To reflect the fact that optional chaining can be called on a nil value, the result of an optional chaining call is always an optional value, even if the property, method, or subscript you are querying returns a nonoptional value.
为什么操场上的类型不是可选的?
let stringOptEmpty: String? = ""
stringOptEmpty?.isEmpty // is true
stringOptEmpty?.isEmpty.dynamicType // Bool.Type
但是下面的代码是
let isOk = stringOptEmpty?.isEmpty.dynamicType
isOk.dynamicType // Optional<Bool.Type>.Type
TLDR;
playground sidebar/column 将动态解析 playground 中的表达式,无论是分配给 variables (mutables/immutables) 的值还是只是 "free-floating"未赋值。
您的第一个示例将 dynamicType
应用于 值,它将解析为该特定值 的 类型(true.dynamicType
: Bool.Type
).
另一方面,您的第二个示例将 dynamicType
应用于 变量 (不可变,但我将使用 变量 与 value) 不同,后者必须具有具体类型,因此将解析为可以容纳任何类型的包装值的类型(true
或 false
) 以及 nil
(这里,nil
具体来说是 Optional<Bool.Type>.None
),无论变量实际持有什么值。因此,在您的第二个示例中,dynamicType
将解析为 Optional<Bool.Type>.Type
。
详情
playground中显示的值sidebar/column一般遵循以下显示规则:
对于赋值表达式,边栏中显示的值是分配的值,例如
var a = 4 // shows '4' a = 2 // shows '2' let b: () = (a = 3) /* shows '()': the _value_ assigned to 'b', which is the _result_ of the assignment 'a = 3', to which a _side effect_ is that 'a' is assigned the value '3'. */
对于不包含赋值的表达式,边栏中显示的值通常是表达式的结果,例如
true // shows 'true' 1 > 3 // shows 'false' let c = 3 c // shows '3' c.dynamicType // shows 'Int.Type'
在您的第一个示例(第 2-3 行)中,我们没有赋值,操场将在解析dynamicType
该值。由于我们正在处理可选值,value 要么只是包装类型的值(在本例中为 true
),要么值为 具体类型 .None
。即使游乐场显示例如let a: Int? = nil
的结果与边栏中的 nil
一样,显示的值实际上与说 let b: String = nil
[= 的 .None
(nil
) 不同62=]
- 对于
let a: Int? = nil
,a
的值实际上是Optional<Int.Type>.None
, - 而对于
let b: String? = nil
,b
的 值 是Optional<String.Type>.None
考虑到这一点,非nil
值 的解析 dynamicType
将是具体的 包裹 类型(在您的示例中,Bool.Type
自然是 true
的类型),而 nil
值的解析 dynamicType
将包括常规可选和包装的类型信息。
struct Foo {
let bar: Bool = true
}
var foo: Foo? = Foo()
/* .Some<T> case (non-nil) */
foo?.bar // true <-- _expression_ resolves to (results in) the _value_ 'true'
foo?.bar.dynamicType // Bool.Type <-- dynamic type of the _result of expression_
true.dynamicType // Bool.Type <-- compare with this
/* .None case (nil) */
foo = nil
foo?.bar.dynamicType // nil <-- _expression_ resolves to the _value_ 'Optional<Foo.Type>.None'
Optional<Foo.Type>.None.dynamicType
// Optional<Foo.Type>.Type <-- compare with this
现在,如果您将值赋值给一个变量,自然该变量必须具有具体类型。由于我们在运行时分配的值 可以是 .None
或 .Some<T>
,变量的类型必须是可以保存这两种情况的值的类型,因此, Optional<T.Type>
(不管变量是 nil
还是非 nil
值)。这是您在第二个示例中显示的情况:variable 的 dynamicType
(此处不可变,但使用 variable 不同于 value) isOk
是可以容纳 .None
和 .Some<T>
的类型,无论变量的实际值是什么,因此 dynamicType
解析为这种类型; Optional<Bool.Type>.Type
.
用括号包裹表达式可以逃避 Swift 游乐场的运行时自省?
有趣的是,如果表达式在应用 .dynamicType
之前用括号括起来,那么 playground 侧边栏会将包裹表达式的 .dynamicType
解析为 类型 的表达式,就好像它的实际值是未知的。例如,(...).dynamicType
中的 (...)
被视为具有具体类型的变量,而不是运行时解析的值。
/* .Some case (non-nil) */
foo?.bar // true
(foo?.bar).dynamicType /* Optional<Bool>.Type <-- as if (...)
is a _variable_ of unknown value */
/* .None case (nil) */
foo = nil
(foo?.bar).dynamicType /* Optional<Bool>.Type <-- as if (...)
is a _variable_ of unknown value */
我们可以进一步注意到,操场上任何用括号包裹的单独表达式都不会解析为任何东西(在侧边栏中)。如果用括号包裹表达式,就好像我们逃避了 sidebar:s 运行时自省(这可以解释为什么包裹在括号中的表达式的 dynamicType
会像 playground 无法使用这些表达式的运行时信息一样解析)
var a = 4 // shows '4'
(a = 2) // shows nothing; can't expand or get details in sidebar
老实说,我无法解释这是为什么,并将其归类为 Swift 游乐场的特点。