【问题标题】:How to conform to a protocol's variables' set & get?如何符合协议的变量设置和获取?
【发布时间】:2017-04-10 19:04:24
【问题描述】:

我正在研究协议以及如何遵守它们。

protocol Human {    
    var height: Int { get set }    
}

struct Boy: Human { 
    var height: Int  { return 5 } // error!
}

我正在尝试学习实现 set 和 get 的不同方法。 但是上面的代码会抛出以下错误:

类型“男孩”不符合协议“人类”

但是如下写不会有任何错误:

struct Boy: Human { 
    var height = 5 // no error
}

当您还可以设置一个变量时,我不明白其中的区别和具体需要实现什么。我查看了不同的问题和教程,但它们都只是写了就走了,没有任何更深入的解释。

编辑: 确保您看到 Imanou 的回答 here。它很好地解释了不同的场景。

【问题讨论】:

  • FWIW struct boy : Human { let height = 5 // error! } 也会产生错误。原因在 Martin 的this 评论中提到。 var 声明一个变量,let 一个常量。作为存储属性,第一个是读/写,第二个是只读

标签: ios swift protocols getter-setter swift-protocols


【解决方案1】:

来自Swift Reference

物业要求

...
该协议没有指定属性应该是存储属性还是计算属性——它只指定了所需的属性名称和类型。
...
属性要求始终声明为变量属性,前缀为 var 关键字。可获取和可设置属性在类型声明后写{ get set }表示,可获取属性写{ get }表示。

你的情况

var height: Int  {return 5} // error!

是一个计算属性,它只能是get,它是一个 的快捷方式

var height: Int {
    get {
        return 5
    }
}

但是Human 协议需要一个可获取和可设置的属性。 您可以遵循存储的 variable 属性(如您所见):

struct Boy: Human { 
    var height = 5
}

或具有 getter 和 setter 的计算属性:

struct Boy: Human { 
    var height: Int {
        get {
            return 5
        }
        set(newValue) {
            // ... do whatever is appropriate ...
        }
    }
}

【讨论】:

  • @Honey: var 声明了一个可以设置和获取的变量
  • @Honey: 协议中的{ get set } 表示可获取和可设置的属性, 是存储属性还是计算属性都没有关系。我已经添加了文档链接。
  • @Honey:“好的理由”或“任何特别的东西”有点含糊。存储属性为值提供存储,计算属性不提供。例如,计算属性也可以将值保存到数据库中。只读计算属性可能根本不需要后备存储。
  • @Honey:如果计算属性的设置者想要保留信息,那么它需要一些后备存储。这可以是存储属性、用户默认值、文件、数据库、Web 服务等。但语言 不需要这些。上面的“无所事事”设置器是有效的 Swift 代码(即使没用 :)
  • @Honey:var 声明一个变量,let 一个常量。作为存储属性,第一个是读/写,第二个是只读的。
【解决方案2】:

先决条件:

进入你的操场,在下面写下 sn-p:

var height: Int {
    get {
        return 5
    }
}    

或类似:

var height: Int {
    return 5
}    

尝试打印height的值,显然有效。到目前为止一切顺利

print(height) // prints 5

但是,如果您尝试将其设置为新值,则会收到错误消息:

height = 8 // ERROR  

错误:无法赋值:'height' 是一个 get-only 属性


答案:

根据马丁的回答,我先写了:

set(newValue) {
    height = newValue 
}

这给我的记忆带来了很多负担,并导致我提出this 的问题。请看一下。因此,我正在考虑要写什么,我有点明白,如果你不想做任何特别的事情,你不应该使用计算属性,而应该只使用普通的存储属性.

于是我写了一个类似的代码

protocol Human {

    var height: Float {get set}

}

struct Boy: Human {

    // inch
    var USheight : Float

    // cm
    var height: Float {
        get {
            return 2.54 * USheight
        }
        set(newValue) {
         USheight = newValue/2.54

        }
    }
}

// 5 ft person
var person = Boy(USheight: 60)
 // interestingly the initializer is 'only' based on stored properties because they
 // initialize computed properties. 


// equals to 152cm person
print(person.height) // 152.4

专业提示:何时应将属性设为只读?

通常,如果您将属性设为只读,即{ get },这是因为这些属性是计算的,您不希望对象控制它。

例如,您有一个 JSON 对象。它有多个大对象,例如:

JSONData
 - userInfo (name, address, age)
 - devices (iPads, iPhones, Mac books)
 - credentials (basic iCloud, pro iCloud, celebrity)

通过将角色设置为只读,您只允许服务器告诉代码库用户的角色。

protocol Credentials {
    var role: String { get }

    init(person: Person)
}

class Person {
    var userInfo: String
    var devices: [String]
    var creds: Credentials {
        Credentials(person: self)
    }

    init(userInfo: userInfo, devices: [String]) {
        self.userInfo = userInfo
        self.devices = devices
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-18
    • 2017-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多