Swift:无法为协议的属性赋值? [英] Swift: Failed to assign value to a property of protocol?

查看:34
本文介绍了Swift:无法为协议的属性赋值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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).

vValueProvider 类型的只读计算属性.通过将协议定义为类协议,编译器知道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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆