ios 如何符合协议的变量设置和获取?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/40820913/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to conform to a protocol's variables' set & get?
提问by Honey
I'm playing around with protocols and how to conform to them.
我正在研究协议以及如何遵守它们。
protocol Human {
var height: Int {get set}
}
struct boy : Human {
var height: Int {return 5} // error!
}
I'm trying to learn different ways that I can implement set and get. However the code above throws the following error:
我正在尝试学习可以实现 set 和 get 的不同方法。但是上面的代码抛出以下错误:
type 'boy' does not conform to protocol 'Human'
“男孩”类型不符合“人类”协议
However writing as below won't have any errors:
但是写如下不会有任何错误:
struct boy : Human {
var height = 5 // no error
}
I don't understand the difference nor what exactly needs to be implemented when you can also seta variable. I looked into different questions and tutorials but they all just write and go without any deeper explanation.
当您还可以设置变量时,我不明白其中的区别,也不明白究竟需要实现什么。我研究了不同的问题和教程,但它们都只是写下来,没有任何更深入的解释。
EDIT:make sure you see Imanou's answer here. It greatly explains the different scenarios.
编辑:确保您在这里看到 Imanou 的回答。它极大地解释了不同的场景。
回答by Martin R
From the Swift Reference:
来自Swift 参考:
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 thevarkeyword. Gettable and settable properties are indicated by writing{ get set }after their type declaration, and gettable properties are indicated by writing{ get }.
属性要求
...
协议没有指定属性应该是存储属性还是计算属性——它只指定了所需的属性名称和类型。
...
属性要求始终声明为变量属性,以var关键字为前缀。Gettable 和 settable 属性{ get set }在它们的类型声明之后用写来表示,gettable 属性用写来表示{ get }。
In your case
在你的情况下
var height: Int {return 5} // error!
is a computed propertywhich can only be get,it is a shortcut for
是一个只能得到的计算属性,它是一个快捷方式
var height: Int {
get {
return 5
}
}
But the Humanprotocol requires a property which is gettable and settable.
You can either conform with a stored variableproperty (as you noticed):
但是该Human协议需要一个可获取和可设置的属性。您可以符合存储的变量属性(如您所见):
struct Boy: Human {
var height = 5
}
or with a computed property which has both getter and setter:
或具有同时具有 getter 和 setter的计算属性:
struct Boy: Human {
var height: Int {
get {
return 5
}
set(newValue) {
// ... do whatever is appropriate ...
}
}
}
回答by Honey
Prerequisite:
先决条件:
Go into your playground and just write the snippet below:
进入你的操场,写下下面的代码片段:
var height: Int {
get {
return 5
}
}
or similarly:
或类似:
var height: Int {
return 5
}
Try to print height's value, obviously works. So far so good
尝试打印height的值,显然有效。到现在为止还挺好
print(height) // prints 5
However if you try to setit to a new value then you'll get an error:
但是,如果您尝试将其设置为新值,则会出现错误:
height = 8 // ERROR
error: cannot assign to value: 'height' is a get-only property
错误:无法分配给值:“高度”是一个只能获取的属性
Answer:
回答:
Based on Martin's answer, I first wrote:
根据马丁的回答,我首先写道:
set(newValue) {
height = newValue
}
Which put a ton of load on my memory and led me to thisquestion. Please take a look. So then I was figuring out what to write, and I kind of understood that if you don't want to do anything special you shouldn'tbe using computed properties and instead you should just use normal stored properties.
这给我的记忆带来了沉重的负担,并让我想到了这个问题。请看一下。然后我想知道要写什么,我有点明白如果你不想做任何特别的事情,你不应该使用计算属性,而应该只使用普通的存储属性。
So I wrote a similarcode
所以我写了一个类似的代码
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
Pro tip: When should you should make your properties read-only?
专业提示:什么时候应该将属性设为只读?
Normally if you make a property to be read-only ie { get }it's because those properties are computedand you don't want the object to have control over it.
通常,如果您将属性设置为只读,即{ get }这是因为这些属性是计算出来的,并且您不希望对象控制它。
Example you have a JSON object. It has multiple big objects like:
例如,您有一个 JSON 对象。它有多个大对象,如:
JSONData
- userInfo (name, address, age)
- devices (iPads, iPhones, Mac books)
- credentials (basic iCloud, pro iCloud, celebrity)
by making the role a read-only you're only allowing the server to tell the code base the role of the user.
通过将角色设置为只读,您只允许服务器告诉代码库用户的角色。
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
}
}

