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
引用的对象)。
v
是ValueProvider
types的只读计算属性。 通过将协议定义为类协议,编译器知道v
是一个引用types ,因此即使引用本身是一个常量,它的v.value
属性也可以被修改。
您的初始代码示例工作,因为在那里的v
属性有一个引用types的typesA
和你的解决方法
set { var tmp = v1 ?? v2 tmp.value = newValue }
因为variables的 (读写)属性可以在任何情况下设置(值types或引用types)。