Extension cannot contain stored property, but why then can static stored property be defined within extension?
I also didn't find any documentation mentioning that static property is allowed in extension.
extension String { static let test = "Test" static var test2 = "Test2" }
error: extensions may not contain stored properties . It means that Swift doesn't support stored properties inside the extension. Therefore, we cannot use the toggleState property to keep the internal state of our toggle button. For this reason, we need a workaround.
Extensions can add new computed properties, but they can't add stored properties, or add property observers to existing properties.
As you may know Swift does not allow stored properties into extensions. That's by design: “Extensions may not contain stored properties.”
It seems you want to add a stored property to a type via protocol extension. However this is not possible because with extensions you cannot add a stored property.
Extensions cannot contain stored instance properties. Why? Because adding an instance property would change the size of instances of that type. What happens if one module adds an extension such that an Int
is now 2 words long? What should then happen when it, for example, gets an Int
from another module where they are still 1 word in size?
The reason why static stored properties are permitted in extensions is simply because they have static lifetime; they exist independently of any instances of the given type you're extending. Really they're nothing more than global stored variables, just namespaced to a type. Therefore they can be freely added without affecting code that has already been compiled without knowledge of them.
It's worth noting however that there are currently three restrictions on defining static stored properties.
static
stored property on a generic typeThis would require separate property storage for each individual specialisation of the generic placeholder(s). For example, with:
struct S<T> { static var foo: Int { return 5 } static let bar = "" // error: Static stored properties not supported in generic types }
Just as foo
is called on individual specialisation of S
, e.g S<Int>.foo
and S<Float>.foo
and not on S
itself (in fact; S
is not even a type currently, it requires that T
be satisfied); bar
would (likely) be the same. It would be called as, for example, S<Int>.bar
, not S.bar
.
This is an important detail because the metatype that a static member is called on is passed to the receiver as the implicit self
argument. This is accessible in static property initialiser expressions; therefore allowing them to call other static methods.
Therefore being able to call the same static property initialiser on different specialisations of a generic type would have the potential to create different property values for each (consider the simple case of static let baz = T.self
). Therefore we need separate storage for each of them.
However, that all being said, there's no real reason why the compiler/runtime cannot do this, and it may well do in a future version of the language. Although one argument against this is that it may produce confusing behaviour in some cases.
For example, consider:
import Foundation struct S<T> { static let date = Date() }
If the runtime implicitly generated new storage for date
each time it gets accessed on a new specialisation of S<T>
, then S<Float>.date
would not equal S<Int>.date
; which may be confusing and/or undesirable.
static
stored property in a protocol extensionThis mostly follows on from the previous point. A static
stored property in a protocol extension would require separate storage for each conforming type of that protocol (but again; there's no reason why the compiler/runtime cannot do this).
This is necessary with protocols, as static
members in protocol extensions are not members on the protocol type itself. They are members on concrete types that conform to the protocol.
For example, if we have:
protocol P {} extension P { static var foo: Int { return 5 } static let bar = "" // error: Static stored properties not supported in generic types // (not really a great diagnostic) } struct S : P {} struct S1 : P {}
We cannot access foo
on the protocol type itself, we cannot say P.foo
. We can only say S.foo
or S1.foo
. This is important because foo
's getter can call out to static protocol requirements on self
; however this isn't possible if self
is P.self
(i.e the protocol type itself), as protocols don't conform to themselves.
The same would (likely) follow for static
stored properties such as bar
.
class
stored propertyI don't believe there would be any problems with such a declaration in the class body itself (it would simply be equivalent to a computed class
property backed by a static
stored property).
However it would be potentially problematic in extensions, because extensions cannot add new members to a Swift class vtable (though they can add to the Obj-C counterpart if applicable). Therefore in most cases they wouldn't be dynamically dispatched to (so would effectively be final
, and therefore static
). Although that being said, class
computed properties are currently permitted in extensions, so it may be permissible in the interests of consistency.
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