why can I do this without any error:
var testDto = ModelDto(modelId: 1) testDto.objectId = 2
while I define this:
protocol DataTransferObject { var objectType: DtoType { get } var parentObjectId: Int { get set } var objectId: Int { get } var objectName: String { get set } } struct ModelDto: DataTransferObject { var objectType: DtoType var parentObjectId: Int var objectId: Int var objectName: String init(modelId: Int) { self.objectType = DtoType.Model self.objectId = modelId self.parentObjectId = -1 self.objectName = String() } }
If the definition in my protocol is mostly ignored (getter, setter definition), why should I use them anyway?
protocol s defines what name has to be in the struct or class that it attached to. If the has { get } then it can be let or var , however if it a { get set } then has to a var only. The advantage is that if someone uses a protocol on a struct or class then those names have to be there.
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.
Protocols provide a blueprint for Methods, properties and other requirements functionality. It is just described as a methods or properties skeleton instead of implementation. Methods and properties implementation can further be done by defining classes, functions and enumerations.
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!
Apple states in the "Swift Programming Language (Swift 3)":
If the protocol only requires a property to be gettable, the requirement can be satisfied by any kind of property, and it is valid for the property to be also settable if this is useful for your own code.
For this reason, the five following Playground code snippets are all valid:
Example #1: constant property
protocol FullyNamed { var fullName: String { get } } struct Duck: FullyNamed { let fullName: String } let scrooge = Duck(fullName: "Scrooge McDuck") print(scrooge.fullName) // returns "Scrooge McDuck"
Example #2: variable property
protocol FullyNamed { var fullName: String { get } } struct Duck: FullyNamed { var fullName: String } var scrooge = Duck(fullName: "Scrooge McDuck") print(scrooge.fullName) // returns "Scrooge McDuck" scrooge.fullName = "Scrooge H. McDuck" print(scrooge.fullName) // returns "Scrooge H. McDuck"
Example #3: computed property (get only)
protocol FullyNamed { var fullName: String { get } } struct Duck: FullyNamed { private var name: String var fullName: String { return name } } let scrooge = Duck(name: "Scrooge McDuck") print(scrooge.fullName) // returns "Scrooge McDuck"
Example #4: computed property (get and set)
protocol FullyNamed { var fullName: String { get } } struct Duck: FullyNamed { private var name: String var fullName: String { get { return name } set { name = newValue } } } var scrooge = Duck(name: "Scrooge McDuck") print(scrooge.fullName) // returns "Scrooge McDuck" scrooge.fullName = "Scrooge H. McDuck" print(scrooge.fullName) // returns "Scrooge H. McDuck"
Example #5: private(set)
variable property
/* Duck.swift located in Sources folder */ protocol FullyNamed { var fullName: String { get } } public struct Duck: FullyNamed { public private(set) var fullName: String public init(fullName: String) { self.fullName = fullName } public mutating func renameWith(fullName: String) { self.fullName = fullName } } /* Playground file */ var scrooge = Duck(fullName: "Scrooge McDuck") print(scrooge.fullName) // returns "Scrooge McDuck" scrooge.renameWith("Scrooge H. McDuck") print(scrooge.fullName) // returns "Scrooge H. McDuck"
Apple also states:
If a protocol requires a property to be gettable and settable, that property requirement cannot be fulfilled by a constant stored property or a read-only computed property.
For this reason, the two following Playground code snippets ARE NOT valid:
Example #1: constant property
protocol FullyNamed { var fullName: String { get set } } struct Duck: FullyNamed { let fullName: String } let scrooge = Duck(fullName: "Scrooge McDuck") // Error message: Type 'Duck' does not conform to protocol 'FullyNamed'
Example #2: computed property (get only)
protocol FullyNamed { var fullName: String { get set } } struct Duck: FullyNamed { private var name: String var fullName: String { return name } } var scrooge = Duck(name: "Scrooge McDuck") // Error message: Type 'Duck' does not conform to protocol 'FullyNamed'
Example #3: computed property (get only)
protocol FullyNamed { var fullName: String { get } } struct Duck: FullyNamed { var fullName: String {return "Scrooge McDuck"} init(fullName: String) { self.fullName = fullName // Error Message Cannot assign to Property: "FullName" is get only } }
As per the official documentation:
The getter and setter requirements can be satisfied by a conforming type in a variety of ways. If a property declaration includes both the get and set keywords, a conforming type can implement it with a stored variable property or a computed property that is both readable and writeable (that is, one that implements both a getter and a setter). However, that property declaration can’t be implemented as a constant property or a read-only computed property. If a property declaration includes only the get keyword, it can be implemented as any kind of property.
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