为什么隐式解包可选项无法使用 `+=` 运算符?

5
为什么用隐式解包可选项时,+=不能正常工作,例如:
var count: Int! = 10
count = count + 10 // This works
count += 10 // this does not work

为什么可选项不像count = count + 10这种情况那样隐式解析?

1
运算符需要一个引用。 - Sulthan
你能再解释一下吗? - Muhammad Zubair Ghori
1
你可以在 += 操作符的左侧添加 ?,例如 count? += 10。如果 count 是一个“常规”的可选类型 Int?,同样适用。如果它的值为 nil,则 += 操作符不会执行任何操作;如果它的值非 nil,则会通过 .some(value) 来增加右侧的 value 值。 - dfrib
如果是这样的话,为什么这里的 count = count + 10 (Int! + 10) 能够工作呢? - Muhammad Zubair Ghori
更有趣的是研究为什么 count += 10 不起作用。在赋值语句 count = count + 10 中,右侧的 count 将被视为一个值并被隐式解包(与隐式解包可选项指定的相同)。然而,count += 10 的情况只是对调用 += 函数的简写,提供了对 count 值的引用和右侧的副本:(+=)(&count, 10)。但由于 count 是一个隐式解包的可选项,它的(隐式)值是不可变的,这等同于调用 (+=)(&(immutable_value_representation), 10) - dfrib
显示剩余3条评论
1个回答

2
由于复合赋值运算符 += 需要左侧为可变的Int变量,因此它无法正常工作。当你传递 count 时,编译器会展开隐式可选项并发送不可变的Int值,这不能作为 += 期望的 inout 参数传递。
如果你真的想这样做,可以对 += 进行重载:
func += (left: inout Int!, right: Int) {
    left = left! + right
}

现在+=会将左侧作为隐式解包的可选类型发送,而在函数内部需要显式进行解包。
var count: Int! = 10
count = count + 10 // 20
count += 10 // 30

那么为什么 count + 10 能够正常工作呢? - Muhammad Zubair Ghori
这个答案是不正确的。在表达式 count += 10 中,count 将会被隐式解包为一个具体的(Int)值,但是该值将是不可变的(当它被隐式提供时,这是隐式解包可选类型的包装值表示的一个属性)。由于 += 方法(/运算符)的第一个参数(或左手边)是一个 inout 参数,自然你不能将不可变的属性传递给它。 - dfrib
上面的自定义 += 运算符只是为当 lhs 是 (inout) Int! 类型,而 rhsInt 类型时提供了更具体的重载。这意味着在调用 count += 10 时不需要隐式解包 count(以匹配 (+=)(inout Int, Int) 的重载),因为该调用有一个完美的重载匹配。然而,重载的主体明确地解包了包装值,允许对其进行修改。 - dfrib
1
@dfri 我没有意识到它实际上正在解包可选项;从错误消息中,我认为它甚至没有尝试。我编辑了我的回答。 - Robert

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接