Hi swift-evolution,
I have an idea for (what I think is) a minor addition to the language. Please forgive me if this has already been discussed at length, all I could find were a few messages from a year and a half ago. :)
One of the things I really like about Swift is that it provides native support for properties. This means that in addition to not having to write getters or setters for every public property on every one of your types when no custom behaviour is needed, it creates a syntactic distinction between methods and properties at the point of use. It makes sense that you would be able to set the value of someProperty on someInstance using the same syntax as you would any local variable rather than using a method called setSomeProperty, for instance.
However, one minor shortcoming of the Swift property system in my opinion is that in certain cases, things that really feel like properties cannot be expressed as such in the language, and we have to fall back on the “old” method of getter and setter methods. Take UIButton, for example. UIButton handles a lot of different cases. It can contain an image, or a label, and then on top of that its appearance can be different depending on which control state it is in. In order to deal with this, it provides setter and getter methods to configure all of this state including the title, font, image, background image and more, all of which take a UIControlState. Now, there’s nothing wrong with this, but it seems to me to be inconsistent with the design of properties in Swift.
So, I propose adding the ability to declare “parameterized properties”, which are exactly as they sound. Instead of writing something like this:
extension MyClass {
func myProperty(for configuration: ConfigurationData) -> Type {
...
}
func setMyProperty(_ value: Type, for configuration: ConfigurationData) {
...
}
}
let instance: MyClass = ...
instance.setMyProperty(someValue, for: .someConfiguration)
One could write something like this (strawman syntax):
extension MyClass {
var myProperty(for configuration: ConfigurationData): Type {
get {
...
}
set {
...
}
}
}
let instance: MyClass = ...
instance.myProperty[for: .someConfiguration] = someValue
Ignoring syntax for a moment, there are a few specifics about this idea I’d be interested in feedback on.
First of all, should these be allowed on stored properties, for use with did/willSet blocks? I can’t think of an instance where this would be useful but I also don’t see why we shouldn’t allow it.
Second of all, should default argument values be allowed? Similarly, I don’t see why not. Furthermore, if all its arguments had default values, it would make sense that you would access a parameterized property in the same way you would a normal property, with no square brackets.
And finally, would it be better to express this idea as named subscripts instead of parameterized properties? Personally I don’t think so because I think the kinds of things this feature would be most useful for share more similarities with properties than with subscripts. But I’m open to alternative views on this.
Let me know what you think!