可选计算属性的两个代码块,为什么不能以这种方式使用 .first?


private var oneAndOnly {
get {
let faceCardIndices = cards.indices.filter({cards[$0].isFaceUp})
return faceCardIndices.count == 1 ? faceCardIndices.first : nil
}
}

private var oneAndOnly {
get {
return cards.indices.filter({cards[$0].isFaceUp}).first
}
}

如果.first在没有元素的情况下返回 nil,我会假设它们是等效的,但它们不是。第一个块实际上给了我一个新的索引,因为第二个块被卡住了。

不同之处在于,只有当正好有一张这样的牌时,第一个块才会找到翻转卡片的索引。

第二个块将返回翻转的第一张卡的索引,即使有多个这样的卡。

换句话说:

faceCardIndices = [5]

这两种方法都将返回5但用于:

faceCardIndices = [1, 5]

第一个将返回nil,而第二个将返回1

在所有其他方面,这些方法是等效的。

在这一行:

return faceCardIndices.count == 1 ? faceCardIndices.first : nil

如果faceCardIndices.count不等于1,那么faceCardIndices.first甚至不会被评估......它只是返回nil.

使用您的其他代码:

return cards.indices.filter({cards[$0].isFaceUp}).first

它会尝试得到.first,无论.filter的结果如何......这可能导致尝试获取零元素的第一个元素

cards是一个空数组时,它们似乎是等效的函数,两个函数都返回nil

在游乐场:

struct Card {
var isFaceUp: Bool
}

struct Test {
var cards = [Card]()
var oneAndOnly: Int? {
get {
let faceCardIndices = cards.indices.filter({cards[$0].isFaceUp})
return faceCardIndices.count == 1 ? faceCardIndices.first : nil
}
}
var oneAndOnly2: Int? {
get {
return cards.indices.filter({cards[$0].isFaceUp}).first
}
}
}
var test = Test()
test.oneAndOnly     //nil
test.oneAndOnly2    //nil

此外,当cards包含 4 张卡片时,一张牌朝上,两个函数返回相同的2索引。

var test = Test()
test.cards.append(Card(isFaceUp: false))
test.cards.append(Card(isFaceUp: false))
test.cards.append(Card(isFaceUp: true))
test.cards.append(Card(isFaceUp: false))
test.oneAndOnly     //2
test.oneAndOnly2    //2

当数组包含 1 个以上的面朝上卡时,差异就会发挥作用,第一个函数返回nil第二个函数返回第一个面朝上卡的索引。这是由于仅在第一个函数中使用的faceCardIndices.count == 1约束。

var test = Test()
test.cards.append(Card(isFaceUp: false))
test.cards.append(Card(isFaceUp: true))
test.cards.append(Card(isFaceUp: true))
test.cards.append(Card(isFaceUp: false))
test.oneAndOnly     //nil
test.oneAndOnly2    //1

最新更新