我必须在 didSet 中的 switch 语句中解包可选两次
I have to unwrap optional twice in switch statement inside didSet
var test: Int! {
didSet {
switch test {
case 1: print("one")
case 2: print("two")
default: print("something else")
}
}
}
var toupleTest: (one: Int, two: Int)! {
didSet {
switch toupleTest! {
case (1, 1): print("one, one")
case (2, 2): print("two, two")
default: print("something else")
}
}
}
test = 2 // prints "two"
toupleTest = (1, 1) // prints "one, one"
在 Int 值的情况下一切正常。
但在元组的情况下,我必须解开可选的两次!否则我会遇到编译错误。
看起来 swift 逻辑不一致。或者这是一个错误?
我认为这是因为元组是 swift 中的值类型。默认类型也是默认类型。基本上你的 unwrap 什么都不做,你只是标记这个值将是非可选的。但是要访问内部的值,你必须打开你的可选元组并达到值
不一致,但是原因有点复杂
为了在 switch
语句中使用类型,它需要符合 Equatable
.
使用新的 struct
类型查看此示例:
struct MyType: Equatable {
let x: Int
static func ==(lhs: MyType, rhs: MyType) -> Bool {
return lhs.x == rhs.x
}
}
var mytypeTest: MyType! {
didSet {
switch mytypeTest {
case MyType(x: 1): print("one")
case MyType(x: 2): print("two")
default: print("something else")
}
}
}
mytypeTest = MyType(x: 1)
这有效,但是如果您从 MyType
中删除 : Equatable
,您将得到错误 Operator function '~=` requires that 'MyType' conform to 'Equatable'.
这是第一个提示。 switch
使用~=
运算符进行比较,类型必须是Equatable
.
那么如果我们尝试使用'~='比较两个元组会发生什么:
if (1, 3) ~= (1, 3) {
print("same")
}
这给出了错误:Type '(Int, Int)' cannot conform to 'Equatable';只有 struct/enum/class 类型可以符合协议 .
因此,这意味着不能在 switch
中使用元组,我们知道这不是真的。
嗯,元组在 switch
中有一个特殊的位置,它们在 模式匹配 中用于解构元组。例如:
let a = (1, 2)
switch a {
case let (x, y):
print("the tuple values are \(x) and \(y)")
}
这会打印 the tuple values are 1 and 2
.
因此,元组在 switch
中用于使用 模式匹配 进行匹配和解构。所以你可以在 switch
中使用元组,即使它不符合 Equatable
因为它有这种特殊用途。
您的示例的问题在于模式与您打开的类型不匹配。您的值的类型是 (Int, Int)?
,模式是 (Int, Int)
.
那么,如何在不强制展开元组值的情况下解决这个问题?通过将 ?
添加到模式来更改您的模式以匹配:
var toupleTest: (one: Int, two: Int)! {
didSet {
switch toupleTest {
case (1, 1)?: print("one, one")
case (2, 2)?: print("two, two")
default: print("something else")
}
}
}
注意:添加 ?
也适用于您的 Int
示例:
var test: Int! {
didSet {
switch test {
case 1?: print("one")
case 2?: print("two")
default: print("something else")
}
}
}
但这不是必需的,因为 Int
是 Equatable
并且 Swift 知道如何比较 Int?
和 Int
是否相等。
var test: Int! {
didSet {
switch test {
case 1: print("one")
case 2: print("two")
default: print("something else")
}
}
}
var toupleTest: (one: Int, two: Int)! {
didSet {
switch toupleTest! {
case (1, 1): print("one, one")
case (2, 2): print("two, two")
default: print("something else")
}
}
}
test = 2 // prints "two"
toupleTest = (1, 1) // prints "one, one"
在 Int 值的情况下一切正常。
但在元组的情况下,我必须解开可选的两次!否则我会遇到编译错误。
看起来 swift 逻辑不一致。或者这是一个错误?
我认为这是因为元组是 swift 中的值类型。默认类型也是默认类型。基本上你的 unwrap 什么都不做,你只是标记这个值将是非可选的。但是要访问内部的值,你必须打开你的可选元组并达到值
不一致,但是原因有点复杂
为了在 switch
语句中使用类型,它需要符合 Equatable
.
使用新的 struct
类型查看此示例:
struct MyType: Equatable {
let x: Int
static func ==(lhs: MyType, rhs: MyType) -> Bool {
return lhs.x == rhs.x
}
}
var mytypeTest: MyType! {
didSet {
switch mytypeTest {
case MyType(x: 1): print("one")
case MyType(x: 2): print("two")
default: print("something else")
}
}
}
mytypeTest = MyType(x: 1)
这有效,但是如果您从 MyType
中删除 : Equatable
,您将得到错误 Operator function '~=` requires that 'MyType' conform to 'Equatable'.
这是第一个提示。 switch
使用~=
运算符进行比较,类型必须是Equatable
.
那么如果我们尝试使用'~='比较两个元组会发生什么:
if (1, 3) ~= (1, 3) {
print("same")
}
这给出了错误:Type '(Int, Int)' cannot conform to 'Equatable';只有 struct/enum/class 类型可以符合协议 .
因此,这意味着不能在 switch
中使用元组,我们知道这不是真的。
嗯,元组在 switch
中有一个特殊的位置,它们在 模式匹配 中用于解构元组。例如:
let a = (1, 2)
switch a {
case let (x, y):
print("the tuple values are \(x) and \(y)")
}
这会打印 the tuple values are 1 and 2
.
因此,元组在 switch
中用于使用 模式匹配 进行匹配和解构。所以你可以在 switch
中使用元组,即使它不符合 Equatable
因为它有这种特殊用途。
您的示例的问题在于模式与您打开的类型不匹配。您的值的类型是 (Int, Int)?
,模式是 (Int, Int)
.
那么,如何在不强制展开元组值的情况下解决这个问题?通过将 ?
添加到模式来更改您的模式以匹配:
var toupleTest: (one: Int, two: Int)! {
didSet {
switch toupleTest {
case (1, 1)?: print("one, one")
case (2, 2)?: print("two, two")
default: print("something else")
}
}
}
注意:添加 ?
也适用于您的 Int
示例:
var test: Int! {
didSet {
switch test {
case 1?: print("one")
case 2?: print("two")
default: print("something else")
}
}
}
但这不是必需的,因为 Int
是 Equatable
并且 Swift 知道如何比较 Int?
和 Int
是否相等。