A类提供字符串值。 B类本身内部有两个A类成员,并提供计算属性" v"选择其中之一。
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的错误,还是协议属性的特殊内容?
答案 0 :(得分:11)
您必须将协议定义为class
协议:
protocol ValueProvider : class {
var value: String {get set}
}
然后
var value: String {
get { return v.value }
set { v.value = newValue }
}
按预期编译和工作(即将新值分配给
v1
v1 != nil
引用的对象和对象
由v2
引用,否则)。
v
是ValueProvider
类型的只读计算属性。
通过将协议定义为编译器知道的类协议
v
是引用类型,因此v.value
即使引用本身是常量,也可以修改属性。
您的初始代码示例有效,因为v
属性具有
类型A
,它是一种引用类型。
你的解决方法
set {
var tmp = v1 ?? v2
tmp.value = newValue
}
可以设置变量的(读写)属性 任何情况(值类型或引用类型)。