【问题标题】:Swift protocols mutability [duplicate]Swift 协议的可变性 [重复]
【发布时间】:2020-05-21 16:37:32
【问题描述】:

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

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 新手,提到的细微差别可能没有任何实际用途,但这种行为让我问自己是否对结构的工作原理缺乏一些基本了解。

【问题讨论】:

  • protocol 定义要实现的最小接口。您的协议 Person 要求实现类型具有名为 nameString 属性,该属性至少可读。 set 的功能是额外的功能,协议不会限制您这样做。

标签: swift struct swift-protocols


【解决方案1】:

协议要求是

一个可以读取的变量name

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

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

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

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

【讨论】:

    【解决方案2】:

    协议只声明所需的接口,而不是符合类型的完整接口。您的符合类型可以添加协议不需要的额外属性/方法。

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

    但是,反过来也行不通。如果协议将属性声明为 { get set },则该属性必须有一个 setter(可变)。

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

        猜你喜欢
        • 2018-07-15
        • 1970-01-01
        • 2023-04-06
        • 2023-04-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多