[swift-evolution] [Proposal] Allow scoped properties from within computed properties
David Sweeris
davesweeris at mac.com
Fri Jan 13 12:41:15 CST 2017
> On Jan 13, 2017, at 11:27, Joseph Newton via swift-evolution <swift-evolution at swift.org> wrote:
>
> Hi,
>
> I've done a lot of Objective-C and have been been a fan of Swift since it's come out, however, there's a small feature of Objective-C that I would really like to see implemented in Swift:
>
> In Objective-C you have a few options implementation-wise when creating properties for your class. You could use the @synthesize statement to have the compiler create the backing ivar along with the appropriate accessor methods or your could use the @dynamic statement to tell the compiler that you're going to create your own accessor methods and backing ivar (if needed).
>
> Additionally, one could use the @synthesize statement to have the compiler create the backing ivar, and then they could create custom accessor methods to supply custom functionality or validation. I use this third case extensively in my Objecitve-C code but there's not a concise way of doing this in Swift.
>
> For example, I might have an Objective-C implementation that looks like this:
>
> @interface Foo : NSObject
> @property (nullable, copy) NSString *bar;
> @end
>
> @implementation Foo
> @synthesize bar = _bar; // Creates ivar '_bar'
>
> - (void)setBar:(NSString *)bar {
> if (bar.length < 100)
> _bar = nil;
> else
> _bar = [bar copy];
> }
>
> @end
>
> Currently, the only way to implement this in Swift - AFAIK - is as follows:
>
> class Foo {
> private var _bar: String?
> public var bar: String? {
> get { return _bar }
> set {
> if (newValue?.characters.count ?? 0) < 100 {
> _bar = nil
> }
> else {
> _bar = newValue.copy() as! String
> }
> }
> }
> }
>
> Although this works, it isn't exactly glamorous. The main drawback of this implementation (unless intended) is that you now have any additional '_bar' variable accessible within the scope of your class.
I believe you can do this using didSet without the `_bar`:
class Foo {
public var bar: String? {
didSet {
if (bar?.characters.count ?? 0) < 100 {
bar = nil
}
}
}
}
> My proposal is to allow stored properties in the declaration block of computed properties. For this example, the '_bar' declaration would simply be moved inside of the declaration block for 'bar':
>
> class Foo {
> public var bar: String? {
> var _bar: String?
>
> get { return _bar }
> set {
> if (newValue?.characters.count ?? 0) < 100 {
> _bar = nil
> }
> else {
> _bar = newValue.copy() as! String
> }
> }
> }
> }
>
> Only the getter and setter methods of 'bar' are allowed to access and modify the stored '_bar' property. My proposal would also allow for multiple stored properties of varying types within the scope of a single computed property. This would also simply atomic synchronization for single variables:
>
> class Foo {
> static var synchronizedBar: String? {
> var queue = DispatchQueue(label: "Foo.synchronizedBar")
> var bar: String?
>
> get { return queue.sync { return bar } }
> set { queue.sync { bar = newValue } }
> }
> }
>
> Are there any suggestions or arguments, for or against, for this proposal?
It's an interesting idea, for sure. Because of the persistent storage required for `_bar`, I think one way to look at what you're proposing is essentially as a way to allow for a variable to be declared publicly as one type, be implemented as another (anonymous, in this case) type under the hood, and to specify a mechanism for automatically converting between the two types.
- Dave Sweeris
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170113/910f422c/attachment.html>
More information about the swift-evolution
mailing list