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:
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 set a 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.
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.
A protocol defines a blueprint of methods, properties, and other requirements. The protocol can then be adopted by a class, structure, or enumeration to provide an actual implementation of those requirements. But there would be a time when you want to restrict protocols to be adopted by a specific class.
Swift 4 allows multiple protocols to be called at once with the help of protocol composition.
A protocol can have properties as well as methods that a class, enum or struct conforming to this protocol can implement. A protocol declaration only specifies the required property name and type.
From the 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 thevarkeyword. Gettable and settable properties are indicated by writing{ get set }after their type declaration, and gettable properties are indicated by writing{ get }.
In your case
var height: Int {return 5} // error! is a computed property which can only be get, it is a shortcut for
var height: Int { get { return 5 } } But the Human protocol requires a property which is gettable and settable. You can either conform with a stored variable property (as you noticed):
struct Boy: Human { var height = 5 } or with a computed property which has both getter and setter:
struct Boy: Human { var height: Int { get { return 5 } set(newValue) { // ... do whatever is appropriate ... } } }
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
print(height) // prints 5 However if you try to set it to a new value then you'll get an error:
height = 8 // ERROR error: cannot assign to value: 'height' is a get-only property
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 this question. 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't be using computed properties and instead you should just use normal stored properties.
So I wrote a similar code
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 Normally if you make a property to be read-only ie { get } it's because those properties are computed and you don't want the object to have control over it.
Example you have a JSON object. It has multiple big objects like:
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 } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With