我刚刚定义了一个非常简单的协议和一个使用泛型的类,它可以处理这个协议。
在标有错误的行中,您会收到错误:“无法在'aObj'中分配给'flag'。
protocol Flag {
var flag: Bool {get set}
}
class TestFlag<T: Flag> {
func toggle(aObj: T) {
if aObj.flag {
aObj.flag = false; // <--- error
} else {
aObj.flag = true; // <--- error
}
}
}
你知道为什么以及为了解决这个问题需要改变什么?
答案 0 :(得分:6)
来自docs:
默认情况下,函数参数是常量。试图改变 函数体内函数参数的值 导致编译时错误。这意味着你无法改变 错误的参数值。
在这种情况下,您可以添加inout
,以便在函数调用之外保留切换:
func toggle(inout aObj: T) {
if aObj.flag {
aObj.flag = false;
else {
aObj.flag = true;
}
}
你也可以做到:
func toggle(var aObj: T) {
}
但这可能达不到你想要的效果。
答案 1 :(得分:2)
manojlds的回答是正确的,因此我接受了。
然而,几天前有一个类似的答案,使用相同的解决方案,但有其他论证(似乎现在已删除)。
论证是关于compliler无法知道协议是用于类,结构还是枚举。使用Swift,协议可以应用于所有这些类型。但结构实例使用按值调用,对于类实例(对象),我们使用按引用调用。
从我的角度来看,这个答案也是正确的,因为你可以通过第二个解决方案解决问题:
@objc
protocol Flag {
var flag: Bool {get set}
}
只需在协议上添加@obj attriute即可。因此,您只能将此协议用于导致结果的类,只允许通过引用调用。因此,编译器不再需要inout
信息。
但我搜索了一个解决方案,以增加协议的重用,并立即使用manojlds建议。