Swift:无法将值分配给协议属性?

A类提供一个string值。 B类有两个Atypes的成员,并提供一个计算属性“v”来select其中的一个。

class A { var value: String init(value: String) { self.value = value } } class B { var v1: A? var v2: A = A(value: "2") private var v: A { return v1 ?? v2 } var value: String { get { return v.value } set { v.value = newValue } } } 

这个代码很简单,它的工作原理。 既然A和B都有一个成员“价值”,我就把它作为一个这样的协议:

 protocol ValueProvider { var value: String {get set} } class A: ValueProvider { var value: String init(value: String) { self.value = value } } class B: ValueProvider { var v1: ValueProvider? var v2: ValueProvider = A(value: "2") private var v: ValueProvider { return v1 ?? v2 } var value: String { get { return v.value } set { v.value = newValue // Error: Cannot assign to the result of the expression } } } 

如果我更改下面的代码

 v.value = newValue 

 var v = self.v v.value = newValue 

它再次运作!

这是一个Swift的bug,还是一些特殊的协议属性?

您必须将协议定义为class协议:

 protocol ValueProvider : class { var value: String {get set} } 

然后

 var value: String { get { return v.value } set { v.value = newValue } } 

编译并按预期工作(即,如果v1 != nil ,则将新值赋给v1 != nil引用的对象,否则将赋予v2引用的对象)。

vValueProvidertypes的只读计算属性。 通过将协议定义为类协议,编译器知道v是一个引用types ,因此即使引用本身是一个常量,它的v.value属性也可以被修改。

您的初始代码示例工作,因为在那里的v属性有一个引用types的typesA

和你的解决方法

 set { var tmp = v1 ?? v2 tmp.value = newValue } 

因为variables的 (读写)属性可以在任何情况下设置(值types或引用types)。