Prerequisite:
Read my blog post on Swift Protocol Compile time check
It will answer to A LOT of your questions. Then read the rest.
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
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 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
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 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
}
}