如何符合协议变量的设置和获取?

How to conform to a protocol's variables' set & get?

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

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

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

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

type 'Boy' does not conform to protocol 'Human'

但是这样写是不会有任何错误的:

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

当您还可以 set 变量时,我不明白其中的区别,也不明白究竟需要实施什么。我研究了不同的问题和教程,但他们都只是写了就走,没有任何更深入的解释。

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

来自Swift Reference

Property Requirements

...
The protocol doesn’t specify whether the property should be a stored property or a computed property—it only specifies the required property name and type.
...
Property requirements are always declared as variable properties, prefixed with the var keyword. Gettable and settable properties are indicated by writing { get set } after their type declaration, and gettable properties are indicated by writing { get }.

你的情况

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

是一个计算出来的属性只能是get,是一个

的快捷方式
var height: Int {
    get {
        return 5
    }
}

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

struct Boy: Human { 
    var height = 5
}

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

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

先决条件:

进入你的游乐场,写下下面的片段:

var height: Int {
    get {
        return 5
    }
}    

或类似的:

var height: Int {
    return 5
}    

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

print(height) // prints 5

但是,如果您尝试 将其设置 为新值,则会出现错误:

height = 8 // ERROR  

error: cannot assign to value: 'height' is a get-only property


答案:

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

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 },那是因为这些属性是 computed 而您不想要该对象控制它。

例如,您有一个 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
    }
}