Why I can't use let in protocol in Swift?

24,926

Solution 1

"A var in a protocol with only get isn't just a let?" No. A let indicates a constant. But that is not the case here. Consider the following:

protocol SomeProtocol {
    var someProperty: String { get }
}

class SomeClass : SomeProtocol {

    var someProperty: String = ""

    func cla () {
        someProperty = "asd"
    }
}

let someInstance = SomeClass()

print(someInstance.someProperty) // outputs ""
someInstance.cla()
print(someInstance.someProperty) // outputs "asd"

The protocol specifies what the conforming class shows to the outside - some property of type String named someProperty which you can at least get.

If the protocol specifies { get } your class can choose to conform via let someProperty: String = "" but it can similarly choose to conform via the above code. If on the other hand the protocol specifies { get set } you cannot use let in the implementation but have to make it set-able as well.

A protocol simply cannot define that a value has to be constant - neither should it, that is an implementation detail that has to be taken care (or decided about) by the class / struct that implements it.

Solution 2

The difference is between

protocol MyProtocol {
    let someProperty: String
}

which makes no sense — a protocol isn't supposed to dictate how someProperty is defined/stored, only that it's available as a property. It could be either a computed or stored property, but that's for the implementer to decide, not the protocol itself.

and

protocol MyProtocol {
    var someProperty: String { get }  // abstract interface
}

struct MyStruct: MyProtocol {
    let someProperty: String  // concrete implementation: stored property
}

struct OtherStruct: MyProtocol {
    let i: Int
    var someProperty: String { return "\(i)" }  // concrete implementation: computed property
}

which is perfectly allowed!

Solution 3

I think a protocol can require that a structure has something, but it can't restrict functionality of struct or object. That shouldn't prevent you from doing what you'd probably like to do in code, for example using a var in the protocol and a let for the implementation is acceptable.

protocol MyProtocol {
    var trythis: Int { get }
}

struct MyStructure: MyProtocol {
    let trythis: Int
}

Solution 4

A property declared with let is considered read-only under the hood. For this reason, a protocol can require that a property be a constant by setting it read-only. This deduction can be verified using some of the Objc runtime functions property_getAttributes.

protocol SomeProtocol {
    var someTypeProperty: Int { get }
}

struct Foo: SomeProtocol {
    let someTypeProperty: Int
}
Share:
24,926

Related videos on Youtube

Massimo Polimeni
Author by

Massimo Polimeni

➜ My LinkedIn profile

Updated on May 30, 2021

Comments

  • Massimo Polimeni
    Massimo Polimeni about 3 years

    I have a doubt about protocols in Swift about the use of var and the keywords { get set }.

    From Apple documentation:

    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. 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.

    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 }.

    I can't understand why I can't use let. A var in a protocol with only get isn't just a let?

    Something like this:

    protocol someProtocol 
    {
       var someProperty: String { get }
    }
    

    it would not be just:

    protocol someProtocol 
    {
       let someProperty: String
    }
    

    I'm missing something?

    • pvg
      pvg over 8 years
      a gettable property can still change values - the protocol implementor can always return different values, the protocol caller simply can't set them. let, on the other hand, defines a constant. it can only be set once and can not have a different value.
    • 0x416e746f6e
      0x416e746f6e over 8 years
      @pvg, why didn't you post this as an answer?
    • sunshinejr
      sunshinejr over 8 years
      yup, this is the correct answer here.
    • pvg
      pvg over 8 years
      @AntonBronnikov Answers to simple questions often end up a competition of who can type the wordiest, least comprehensible thing. For little things, easier to just comment. Also, lazy.
    • 0x416e746f6e
      0x416e746f6e over 8 years
      @pvg, I get your point. One should please to be right.
  • Massimo Polimeni
    Massimo Polimeni over 8 years
    Looking back it was so simple and obvious, in protocols are allowed only functions (then properties) but I always prefer ask and solve any doubts; now the use of { get set } it's clear as ever, thanks again!
  • mfaani
    mfaani about 5 years
    a protocol isn't supposed to dictate how someProperty is defined/stored Doesn't a protocol define variable name/type/must be settable or not? Why didn't Apple provide more granularity and allow to define both let and var properties?
  • mfaani
    mfaani about 5 years
    A protocol simply cannot define that a value has to be constant - neither should it Why Not? Why didn't Apple provide more granularity and allow to define both let and var properties? Or you're saying while Apple could have opted what I said, instead they opted that the flexibility to be given at the implementation level