Swift:无法为协议的属性赋值? [英] Swift: Failed to assign value to a property of protocol?
问题描述
A 类提供字符串值.B类内部有两个A类成员,并提供了一个计算属性v"来选择其中一个.
Class A provides a string value. Class B has two members of A type inside itself, and provide a computed property "v" to choose one of them.
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 都有成员值",我将其设为这样的协议:
This code is simple and it works. Since both the A and B have a member "value", I make it a protocol like this:
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,还是协议的特性?
Is this a bug of Swift, or something special for the property of protocols?
推荐答案
您必须将协议定义为 class
协议:
You have to define the protocol as a class
protocol:
protocol ValueProvider : class {
var value: String {get set}
}
然后
var value: String {
get { return v.value }
set { v.value = newValue }
}
编译并按预期工作(即,将新值分配给v1
引用的对象,如果 v1 != nil
,以及对象否则由 v2
引用).
compiles and works as expected (i.e. assigns the new value to the
object referenced by v1
if v1 != nil
, and to the object
referenced by v2
otherwise).
v
是 ValueProvider
类型的只读计算属性.通过将协议定义为类协议,编译器知道v
是一个引用类型,因此它的 v.value
即使引用本身是一个常量,也可以修改属性.
v
is a read-only computed property of the type ValueProvider
.
By defining the protocol as a class protocol the compiler knows
that v
is a reference type, and therefore its v.value
property can be modified even if the reference itself is a constant.
您的初始代码示例有效,因为 v
属性具有类型 A
是一个引用类型.
Your initial code example works because there the v
property has
the type A
which is a reference type.
以及您的解决方法
set {
var tmp = v1 ?? v2
tmp.value = newValue
}
之所以有效是因为变量的(读写)属性可以在任何情况(值类型或引用类型).
works because (read-write) properties of variables can be set in any case (value type or reference type).
这篇关于Swift:无法为协议的属性赋值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!