Swift 协议可变性

Swift protocols mutability

我目前对协议中的可获取属性有点困惑。考虑这个例子:

protocol Person {
    var name: String { get }
}

我原以为 name 属性 是只读的,但我发现您可以在没有编译器投诉的情况下更改该值:

struct Driver: Person {
    var name: String
}

var driver = Driver(name: "Ryan")
driver.name = "Changed!"

如果我们用 let 关键字定义 driver,那么编译器会引发错误,但如果我理解正确,它与协议无关,因为常量结构在设计上是不可变的 Swift.

方法交互的行为符合我的预期:

extension Person {
    mutating func changeName(_ newName: String) {
        self.name = newName    // Error: 'name' is a get-only property
    }
}

我是 Swift 的新手,提到的细微差别可能没有任何实际用处,但这种行为让我问自己是否缺乏对结构如何工作的一些基本了解。

协议要求是

a variable name which can be read

这并不意味着采用该协议的结构体中的变量一定是只读的。

在代码中,您直接在 Driver 类型中更改变量,不涉及协议。

另一方面,如果您注释协议类型,您会得到预期的错误

var driver : Person = Driver(name: "Ryan")
driver.name = "Changed!" // Cannot assign to property: 'name' is a get-only property

一个协议只声明了需要的接口,而没有声明符合类型的完整接口。您的符合类型可以添加协议不需要的额外 properties/methods。

getters和setter也是如此。如果协议 属性 要求是 get,这意味着一致性类型必须具有 属性 的 getter,但这并不意味着它不能具有 setter 也是如此。

然而,反之则不然。如果协议将 属性 声明为 { get set },则 属性 必须具有 setter(可变)。

苹果documentation很好地解释了这一点。

The getter and setter requirements can be satisfied by a conforming type in a variety of ways. If a property declaration includes both the get and set keywords, a conforming type can implement it with a stored variable property or a computed property that is both readable and writeable (that is, one that implements both a getter and a setter). However, that property declaration can’t be implemented as a constant property or a read-only computed property. If a property declaration includes only the get keyword, it can be implemented as any kind of property.