Swift Protocol get only settable? Swift Protocol get only settable? ios ios

Swift Protocol get only settable?


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.


Consider the following:

var testDto = ModelDto(modelId: 1)

The variable testDto type here is known to be ModelDto. ModelDto is known to have a mutable variable var objectId: Int. You're free to modify objectId because you're accesses the object through the ModelDto interface and not via the protocol interface where it is only gettable.

Try the following:

var testDto: DataTransferObject = ModelDto(modelId: 1)testDto.objectId = 2 // compiler error

The above example shouldn't compile. Because the type of testDto is only known to be DataTransferObject, we don't know that the underlying implementation has a settable property. We only know about the gettable property declared in the protocol.

In short, you've declared ModelDto to have a get/set variable, so it would be quite strange indeed if Swift did not let you set it. Having a get only variable would rely on you referncing the object via the protocol or changing objectId on ModelDTO to be a let variable.

EDIT: To address your confusion about why ModelDto is allowed to have a settable variable. It is the same as how ModelDto is allowed to have other functions than the ones defined in the protocol. Getters and setters are actually just functions, so the protocol requiring a getter does not preclude an implementation from also having a setter. The same is possible in Objective C. Protocols are descriptive, not restrictive.