Swift协议可变性

问题描述 投票:1回答:3

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

protocol Person {
    var name: String { get }
}

我希望name属性为只读,但是我发现您可以更改该值而不会引起编译器投诉:

struct Driver: Person {
    var name: String
}

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

如果使用driver关键字定义let,则编译器会引发错误,但如果我理解正确,则与协议无关,因为常量结构在Swift中是不变的。

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

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

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

swift struct swift-protocols
3个回答
3
投票

协议要求是

可以读取的变量name

这并不意味着采用此协议的结构中的变量必须是只读的。

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

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

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

2
投票

协议仅声明必需的接口,而没有声明符合类型的完整接口。您的符合类型可以添加协议不需要的其他属性/方法。

吸气剂和塞脂剂也是如此。如果协议属性要求为get,则表示一致类型必须具有属性的吸气剂,但这并不意味着它也不能具有setter

但是,同样的方法在其他方面是行不通的。如果协议将某个属性声明为{ get set },则该属性必须具有设置器(可变)。


1
投票

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

可以通过多种方式通过符合类型来满足吸气剂和设置剂的要求。如果属性声明同时包含get和set关键字,则符合类型可以使用存储变量属性或既可读又可写的计算属性(即,同时实现getter和setter的)来实现它。但是,该属性声明不能实现为常量属性或只读的计算属性。如果属性声明仅包含get关键字,则可以将其实现为任何类型的属性。

© www.soinside.com 2019 - 2024. All rights reserved.