There was a proposal for custom behaviors using `@`, which if I recall would offer encapsulation along the lines of what you're proposing. It was an extensively designed system which was deferred for consideration, but which would be in scope again in phase 2. The proposal is in the swift-evolution repository--does that address your use case?<br><div class="gmail_quote"><div dir="ltr">On Fri, Jan 13, 2017 at 11:27 Joseph Newton via swift-evolution <<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg">Hi,<br class="gmail_msg"><br class="gmail_msg"></div>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:<br class="gmail_msg"><br class="gmail_msg"></div>In Objective-C you have a few options implementation-wise when creating properties for your class. You could use the <i class="gmail_msg">@synthesize </i>statement to have the compiler create the backing ivar along with the appropriate accessor methods<i class="gmail_msg"> </i>or your could use the <i class="gmail_msg">@dynamic</i> statement to tell the compiler that you're going to create your own accessor methods and backing ivar (if needed).<br class="gmail_msg"><br class="gmail_msg"></div>Additionally, one could use the <i class="gmail_msg">@synthesize</i> 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.<br class="gmail_msg"><br class="gmail_msg"></div>For example, I might have an Objective-C implementation that looks like this:<br class="gmail_msg"><br class="gmail_msg"></div>@interface Foo : NSObject<br class="gmail_msg"></div><div class="gmail_msg">@property (nullable, copy) NSString *bar;<br class="gmail_msg"></div>@end<br class="gmail_msg"><br class="gmail_msg"></div>@implementation Foo<br class="gmail_msg"></div><div class="gmail_msg">@synthesize bar = _bar; // Creates ivar '_bar'<br class="gmail_msg"></div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">- (void)setBar:(NSString *)bar {<br class="gmail_msg"></div><div class="gmail_msg"> if (bar.length < 100)<br class="gmail_msg"></div><div class="gmail_msg"> _bar = nil;<br class="gmail_msg"></div><div class="gmail_msg"> else<br class="gmail_msg"></div><div class="gmail_msg"> _bar = [bar copy];<br class="gmail_msg"></div><div class="gmail_msg">}<br class="gmail_msg"></div><div class="gmail_msg"><br class="gmail_msg"></div>@end<br class="gmail_msg"><br class="gmail_msg"></div>Currently, the only way to implement this in Swift - AFAIK - is as follows:<br class="gmail_msg"><br class="gmail_msg"></div>class Foo {<br class="gmail_msg"></div> private var _bar: String?<br class="gmail_msg"></div> public var bar: String? {<br class="gmail_msg"></div> get { return _bar }<br class="gmail_msg"></div> set {<br class="gmail_msg"></div> if (newValue?.characters.count ?? 0) < 100 {<br class="gmail_msg"></div> _bar = nil<br class="gmail_msg"><div class="gmail_msg"> }<br class="gmail_msg"></div><div class="gmail_msg"> else {<br class="gmail_msg"></div><div class="gmail_msg"> _bar = newValue.copy() as! String<br class="gmail_msg"></div><div class="gmail_msg"> }<br class="gmail_msg"></div><div class="gmail_msg"><div class="gmail_msg"> }<br class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"> }<br class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg">}<br class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">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. <br class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">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':<br class="gmail_msg"><br class="gmail_msg">class Foo {<br class="gmail_msg"> public var bar: String? {<br class="gmail_msg"> var _bar: String?<br class="gmail_msg"><br class="gmail_msg"> get { return _bar }<br class="gmail_msg"> set {<br class="gmail_msg"> if (newValue?.characters.count ?? 0) < 100 {<br class="gmail_msg"> _bar = nil<br class="gmail_msg"><div class="gmail_msg"> }<br class="gmail_msg"></div><div class="gmail_msg"> else {<br class="gmail_msg"></div><div class="gmail_msg"> _bar = newValue.copy() as! String<br class="gmail_msg"></div><div class="gmail_msg"> }<br class="gmail_msg"></div> }<br class="gmail_msg"> }<br class="gmail_msg">}<br class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">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:<br class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">class Foo {<br class="gmail_msg"></div><div class="gmail_msg"> static var synchronizedBar: String? {<br class="gmail_msg"></div><div class="gmail_msg"> var queue = DispatchQueue(label: "Foo.synchronizedBar")<br class="gmail_msg"></div><div class="gmail_msg"> var bar: String?<br class="gmail_msg"></div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg"> get { return queue.sync { return bar } }<br class="gmail_msg"></div><div class="gmail_msg"> set { queue.sync { bar = newValue } }<br class="gmail_msg"></div><div class="gmail_msg"> }<br class="gmail_msg"></div><div class="gmail_msg">}<br class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">Are there any suggestions or arguments, for or against, for this proposal?<br class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">-- Joe Newton<br class="gmail_msg"></div></div></div></div></div></div></div></div>
_______________________________________________<br class="gmail_msg">
swift-evolution mailing list<br class="gmail_msg">
<a href="mailto:swift-evolution@swift.org" class="gmail_msg" target="_blank">swift-evolution@swift.org</a><br class="gmail_msg">
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" class="gmail_msg" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class="gmail_msg">
</blockquote></div>