protocol Deck {
var cards: [String] {get set} // {get mutable set}
}
struct MyDeck: Deck {
var cards: [String] = (1...7).map {_ in return String(rand())}
}
Just interested do I need to specify {get mutable set} in protocol? Can't find any docs about why not using mutable keyword in setter declaration if my setter mutates my struct
First of all note that the keyword of discussion is mutating
, not mutable
.
set
is mutating
mutating
is the default state for setters, and hence you needn't explicitly use the mutating
keyword to specify this.For getter and setters, the following default behaviour holds
get
is nonmutating
as per defaultset
is mutating
as per defaultHence, a protocol specifying ... { get set }
for, say (as in your example), a computed property, expects the default nonmutating get
and mutating set
of a struct
conforming to such a protocol
protocol Deck {
var cards: [String] {get set}
}
// implicitly, OK
struct MyDeckA: Deck {
var mutateMe: Int = 0
var cards: [String] {
get { return ["foo"] }
set { mutateMe += 1 }
}
}
// explicitly, OK
struct MyDeckB: Deck {
var mutateMe: Int = 0
var cards: [String] {
nonmutating get { return ["foo"] }
mutating set { mutateMe += 1 }
}
}
/* error, MyDeckC does not conform to Deck
(mutating getter, wheres a nonmutating one is blueprinted!) */
struct MyDeckC: Deck {
var mutateMe: Int = 0
var cards: [String] {
mutating get { return ["foo"] }
mutating set { mutateMe += 1 }
}
}
In case we want a getter or setter that deviates from the default cases above, we need to specify this (in the protocol as well as explicitly in say a struct conforming to such a protocol).
protocol Deck {
var cards: [String] {mutating get nonmutating set}
}
/* when conforming to this non-default get/set setup blueprinted in
protocol Deck, we need to explicitly specify our non-default
(w.r.t. mutating) getter and setter */
struct MyDeckD: Deck {
var mutateMe: Int = 0
var cards: [String] {
mutating get { mutateMe += 1; return ["foo"] }
nonmutating set { print("I can't mutate self ...") }
}
}
Finally, interestingly, if we (for some protocol property) blueprint a setter as the default (... {get set}
), i.e., defaulted as mutating set
, we may still conform to such a protocol with an explicitly nonmutating
setter
protocol Deck {
var cards: [String] {get set}
}
struct MyDeckE: Deck {
var mutateMe: Int = 0
var cards: [String] {
get { return ["foo"] }
nonmutating set { print("I can't mutate self ...") }
/* setter cannot mutate self */
}
}
I can assume that this is allowed as we let the structure that conforms to the protocol contain a setter that is more restrictive than the blueprinted one, with regard to mutating self
. Naturally the same holds if we blueprint a mutating
getter: we may still conform to such a protocol with a nonmutating
one.
protocol Deck {
var cards: [String] {mutating get set}
}
struct MyDeckF: Deck {
var mutateMe: Int = 0
var cards: [String] {
nonmutating get { print("I can't mutate self ..."); return ["foo"] }
/* getter cannot mutate self */
set { mutateMe += 1 }
}
}
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