Why I can't use let in protocol in Swift?
IosSwiftProtocolsGetter SetterSwift ProtocolsIos Problem Overview
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?
Ios Solutions
Solution 1 - Ios
"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 - Ios
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 - Ios
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 - Ios
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
}