Personally I write a lot of UI code, and so the pattern is used quite a lot to 
expose certain properties, for example a button's `title` and `textColor`.

Oftentimes, the view hierarchy itself is complicated enough that exposing views 
directly is not feasible, so a host of such aliases are needed to offer a 
usable public API.

– Harshil

>> On 26-May-2017, at 1:04 AM, Charles Srstka <[email protected]> wrote:
>> 
>>> On May 25, 2017, at 1:34 PM, Xiaodi Wu via swift-evolution 
>>> <[email protected]> wrote:
>>> 
>>> On Thu, May 25, 2017 at 10:08 AM, Harshil Shah via swift-evolution 
>>> <[email protected]> wrote:
>>> Hi all,
>>> 
>>> The idea behind this is to add a shorter, cleaner syntax for the common 
>>> pattern of using computed properties to provide public API for properties 
>>> of private variables.
>>> 
>>> For example:
>>> 
>>> public var foo: Type {
>>>     get { return privateBar.baz }
>>>     set { privateBar.baz = newValue }
>>> }
>>> 
>>> While this is a great improvement over the previous convention of 
>>> `someVar:` and `setSomeVar:` as found in a lot of UIKit, it still has some 
>>> issues.
>>> 
>>> It is overly verbose for the task at hand. It requires specifying the type 
>>> of property that the variable is effectively acting as an alias for, 
>>> stating the property name twice, and also doesn’t preclude the possibility 
>>> of mistakenly using `privateBar.baz = foo` in the setter, which looks 
>>> correct at a glance but just assigns the existing value of `baz` back to 
>>> it, effectively doing nothing.
>>> 
>>> It could potentially be shortened, as follows:
>>> 
>>> public alias var foo = privateBar.baz
>>> 
>>> This new syntax omits additional type information which could be inferred 
>>> from the type of the original variable, prevents any assignment mistakes in 
>>> the setter, reduces the number of lines of code needed, and makes it clear 
>>> that the purpose of the variable is simply to act as an alias.
>>> 
>>> I have used the `alias` keyword above as a placeholder. I suppose there 
>>> might be needed some way to clarify that `foo` is still a computed 
>>> property, and not a stored property declared as having the value of 
>>> `privateBar.baz`. I realise that introducing a new keyword is not a trivial 
>>> change, however this was simply the best idea I could come up with; I’m 
>>> sure the community can find better solutions.
>>> 
>>> At the same time, a new keyword makes the intention of the variable 
>>> explicit, and would break no Swift 3.* code.
>>> 
>>> I realise this is just syntactic sugar, however the pattern is common 
>>> enough that I feel like it merits some discussion.
>> 
>> It's reasonable to ask for sugar when a common pattern is unusually verbose, 
>> but I'd like to explore if that's really the case here.
>> 
>> I've had occasion to use a public computed property which returns a private 
>> stored property, but it's _never_ been only that. There's usually some 
>> tricky validation going on or something else that prevents me from just 
>> making the private property `public` or `public internal(set)`. It seems 
>> you're showing one such case where the stored property is in fact stored in 
>> some other variable of a different type. Is it actually very common? In what 
>> sort of programming?
> 
> I’ve used this pattern on occasion to expose properties of value types to KVO:
> 
> class SomeObservableThing: NSObject {
>       var someValueType: SomeValueType {
>               willSet {
>                       self.willChangeValue(forKey: #keyPath(foo))
>                       self.willChangeValue(forKey: #keyPath(bar))
>               }
>               didSet {
>                       self.didChangeValue(forKey: #keyPath(foo))
>                       self.didChangeValue(forKey: #keyPath(bar))
>               }
>       }
> 
>       @objc private static let automaticallyNotifiesObserversOfFoo = false
>       @objc var foo: Foo {
>               get { return self.someValueType.foo }
>               set { self.someValueType.foo = newValue }
>       }
> 
>       @objc private static let automaticallyNotifiesObserversOfBar = false
>       @objc var bar: Bar {
>               get { return self.someValueType.bar }
>               set { self.someValueType.bar = newValue }
>       }
> }
> 
> The accessors on foo and bar aren’t really the most obnoxious bits of 
> boilerplate here, though.
> 
> Charles
> 
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to