<div id="compose" contenteditable="true" style="padding-left: 16px; padding-right: 16px; padding-bottom: 8px;"><div>But can your code compile and run? How can you access instance properties via class interface?</div><div><br></div><div>I didn't bring up this behavior of computed class variables as an argument for unifying "class" and "static". I brought up it to demonstrate the similarity between computed and stored type properties, even on limitation/issue level, which is an argument for unifying "class" and "static". <br><br><div class="acompli_signature">- Ling</div></div></div>
<div class="gmail_quote">_____________________________<br>From: Jordan Rose <<a dir="ltr" href="mailto:jordan_rose@apple.com" x-apple-data-detectors="true" x-apple-data-detectors-type="link" x-apple-data-detectors-result="1">jordan_rose@apple.com</a>><br>Sent: Thursday, December 10, 2015 7:06 PM<br>Subject: Re: [swift-evolution] Unify `static` and `class` keywords<br>To: Ling Wang <<a dir="ltr" href="mailto:an00na@gmail.com" x-apple-data-detectors="true" x-apple-data-detectors-type="link" x-apple-data-detectors-result="4">an00na@gmail.com</a>><br>Cc: swift-evolution <<a dir="ltr" href="mailto:swift-evolution@swift.org" x-apple-data-detectors="true" x-apple-data-detectors-type="link" x-apple-data-detectors-result="5">swift-evolution@swift.org</a>><br><br><br> <meta content="text/html charset=utf-8"> <div class=""> Here is your code, minus the "class" qualifier. </div> <div class=""> <br class=""> </div> <blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""> <div class=""> <div class=""> var backingVarForFooI = 0 </div> </div> <div class=""> <div class=""> <br class=""> </div> </div> <div class=""> <div class=""> class Foo { </div> </div> <div class=""> <div class=""> var i: Int { <i class=""> // was "class"</i> </div> </div> <div class=""> <div class=""> get { </div> </div> <div class=""> <div class=""> return backingVarForFooI </div> </div> <div class=""> <div class=""> } </div> </div> <div class=""> <div class=""> </div> </div> <div class=""> <div class=""> set { </div> </div> <div class=""> <div class=""> backingVarForFooI = newValue </div> </div> <div class=""> <div class=""> print("Foo.i.set \(newValue)") </div> </div> <div class=""> <div class=""> } </div> </div> <div class=""> <div class=""> } </div> </div> <div class=""> <div class=""> } </div> </div> <div class=""> <div class=""> <br class=""> </div> </div> <div class=""> <div class=""> class Bar: Foo { </div> </div> <div class=""> <div class=""> override var i: Int { <i class="">// was "class"</i> </div> </div> <div class=""> <div class=""> didSet { </div> </div> <div class=""> <div class=""> print("Bar.i.didSet \(i)") </div> </div> <div class=""> <div class=""> } </div> </div> <div class=""> <div class=""> } </div> </div> <div class=""> <div class=""> } </div> </div> <div class=""> <div class=""> <br class=""> </div> </div> <div class=""> <div class=""> print(Bar.i) </div> </div> <div class=""> <div class=""> Foo.i = 3 </div> </div> <div class=""> <div class=""> print(Bar.i) </div> </div> </blockquote> <span id="x-apple-selection:end"></span> <div class=""> <br class=""> </div> <div class=""> Now, clearly this is rather silly code, but my point is "if you choose to use a global variable as the backing storage of a computed property, you can mutate it in multiple ways". Whether the computed property is a class property or an instance property doesn't affect that. </div> <div class=""> <br class=""> </div> <div class=""> That's not an argument against unifying "class" and "static". It's just pointing out that the existing behavior of computed class variables isn't an argument <i class="">for</i> unifying "class" and "static" either. </div> <div class=""> <br class=""> </div> <div class=""> Jordan </div> <div class=""> <br class=""> </div> <br class=""> <div> <blockquote class=""> <div class=""> On Dec 10, 2015, at 12:19, Ling Wang < <a href="mailto:an00na@gmail.com" class="">an00na@gmail.com</a>> wrote: </div> <br class="Apple-interchange-newline"> <div class=""> <meta content="text/html charset=utf-8" class=""> <div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""> <div class=""> I just realized that I wrote `overload` when I meant `override` in some places. Sorry for that. </div> <div class=""> <br class=""> </div>I didn’t say it is a bug, just an issue. An issue like I only get notified when I draw money from the bank account I inherited from my father but not when my father draw from it. :p <div class=""> <br class=""> </div> <div class=""> The underlying implementation may match match that for instance computed properties. But we can't demonstrate this behavior on instance properties, can we? How can a Swift user trigger super setter without triggering subclass observer when writing to an instance property? </div> <div class=""> <br class=""> </div> <div class=""> There is no clear solution to overriding setter and overriding with observer at the same time. </div> <div class=""> <br class=""> </div> <div class=""> When I talked about the issue, my major point is that there is no necessary and meaningful difference between stored and calculated type properties, even the issues are the same, so we can unite them with a single keyword. </div> <div class=""> <br class="">I thought I got it from your first mail, but after these discussion I got lost:( What exactly is your concern of stored type properties from my proposal? Why doesn't it apply to calculated type properties? <br class=""> <br class=""> <div class=""> - Ling <br class=""> <div class=""> <br class=""> <div class=""> <blockquote class=""> <div class=""> On Dec 10, 2015, at 12:17 PM, Jordan Rose < <a href="mailto:jordan_rose@apple.com" class="">jordan_rose@apple.com</a>> wrote: </div> <br class="Apple-interchange-newline"> <div class=""> <meta content="text/html charset=utf-8" class=""> <div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""> <div class=""> The current behavior is not a bug; it matches the behavior for instance computed properties. To put it another way, if the base class's computed implementation stored values in a dictionary keyed by 'self', it would effectively be an implementation of true class properties. (People do indeed do this in Objective-C, although it's not common.) </div> <div class=""> <br class=""> </div> <div class=""> We definitely don't want setting a base class property to invoke an arbitrary number of arbitrarily-ordered observers. Moreover, what if some of the subclasses actually override the setter entirely, instead of just adding an observer? That's clearly not implementable. </div> <div class=""> <br class=""> </div> <div class=""> Again, I'm not saying you/we can't pick a behavior and stick with it. I just want the tradeoffs to be clear. </div> <div class=""> <br class=""> </div> <div class=""> Jordan </div> <div class=""> <br class=""> </div> <br class=""> <div class=""> <blockquote class=""> <div class=""> On Dec 10, 2015, at 7:23, Ling Wang < <a href="mailto:an00na@gmail.com" class="">an00na@gmail.com</a>> wrote: </div> <br class="Apple-interchange-newline"> <div class=""> <meta content="text/html charset=utf-8" class=""> <div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""> <div class=""> When verifying my class object modal I actually found one issue of the current class property observers. </div> <div class=""> <br class=""> </div> <div class=""> In the current implementation, when super class’s class property setter is called, subclasses’ observers don’t get called. But after the call of super setter, the value of this property accessed via subclasses(suppose them don’t overload get/set) does change. It means their properties are changed without their knowing it even though they explicitly define observers to observe the changes. </div> <div class=""> <br class=""> </div> <div class=""> <div class=""> ``` </div> <div class=""> var backingVarForFooI = 0 <br class=""> <br class="">class Foo { <br class=""> class var i: Int { <br class=""> get { <br class=""> return backingVarForFooI <br class=""> } <br class=""> <br class=""> set { <br class=""> backingVarForFooI = newValue <br class=""> print("Foo.i.set \(newValue)") <br class=""> } <br class=""> } <br class="">} <br class=""> <br class="">class Bar: Foo { <br class=""> override class var i: Int { <br class=""> didSet { <br class=""> print("Bar.i.didSet \(i)") <br class=""> } <br class=""> } <br class="">} <br class=""> <br class="">print(Bar.i) <br class="">Foo.i = 3 <br class="">print(Bar.i) </div> <div class=""> ``` </div> </div> <div class=""> <br class=""> </div> <div class=""> If we think about it, it doesn’t matter whether the proper is stored or calculated. Storage is just the implementation details, it doesn’t affect the interface or the concept. Besides, even calculated properties need storage if they are mutable. </div> <div class=""> <br class=""> </div> <div class=""> After super class changes a property, people expect to get the changed value when they access the property via their subclasses(suppose they don’t overload get/set) and expect the corresponding observers to get called. So the class object modal that I speculated sharing properties among all subclasses and super class and notifying them about property changes is the only sound modal in this aspect. So the concern about overloading stored type properties with observers is not only about stored type properties but about all type properties. </div> <div class=""> <br class=""> </div> <div class=""> So there is nothing special to separate stored type properties from calculated type properties. It supports my proposal to unite them under a more general keyword. </div> <div class=""> <br class=""> </div> <div class=""> - Ling </div> <div class=""> <br class=""> </div> <div class=""> <blockquote class=""> <div class=""> On Dec 9, 2015, at 10:23 AM, Ling Wang < <a href="mailto:an00na@gmail.com" class="">an00na@gmail.com</a>> wrote: </div> <br class="Apple-interchange-newline"> <div class=""> <meta content="text/html charset=utf-8" class=""> <div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""> <div class=""> This is a legit concern that I didn’t consider before. </div> <div class=""> <br class=""> </div> <div class=""> I think there are several options, from the most general to the most subtle: </div> <div class=""> 1. Stored type properties are implicit `final`, so behave exactly the same as the current static stored properties. </div> <div class=""> 2. Stored type vars are implicit `final`, as you suggested, so behave exactly the same as the current static stored vars. All other type properties(including stored type lets) are normally overridable. </div> <div class=""> 3. Store type vars are overridable but can not be observed. </div> <div class=""> <br class=""> </div> <div class=""> There could be a even more subtle option if my understanding of how classes exist in runtime is correct. </div> <div class=""> <br class=""> </div> <div class=""> In my understanding, classes exist as singleton instances of their meta classes. If it is true, which I believe is the image in most people’s heads if they know about meta classes, then the class objects tree is exactly the same as the class hierarchy tree. Every subclass object contains(or points to) its super class object in its layout. The super class part is shared by all subclass objects and the super class object per se. So stored type properties are conceptually and naturally shared by the super class and all its subclasses, which behave exactly like the current static stored properties. </div> <div class=""> <br class=""> </div> <div class=""> In this modal, the 4th option is: </div> <div class=""> 4. Stored type vars are overridable and observable. When they are assigned new values, all their property observers defined in the class hierarchy are called, calling order is not significant, the reason of which will be addressed later. </div> <div class=""> <br class=""> </div> <div class=""> Unfortunately, there is one last catch: if more than one classes assign a value to the property within their didSet observer, the final result is undefined. </div> <div class=""> <br class=""> </div> <div class=""> This issue can not even be resolved by ordering observer calls from top to bottom in the class hierarchy because we can not meaningfully define the order within the same level if there are more than one subclasses in it. </div> <div class=""> <br class=""> </div> <div class=""> So one addition to option 4: </div> <div class=""> 4-1. Stored type vars’ didSet observers are not allowed to reassign value to the observed property. </div> <div class=""> <br class=""> </div> <div class=""> But it is such a corner case that probably this limitation is acceptable. </div> <div class=""> <br class=""> </div> <div class=""> What do you think? Is my understanding of class objects correct? Which option do you like best? </div> <div class=""> <br class=""> </div> <div class=""> - Ling </div> <div class=""> <br class=""> </div> <div class=""> <blockquote class=""> <div class=""> On Dec 8, 2015, at 5:40 PM, Jordan Rose < <a href="mailto:jordan_rose@apple.com" class="">jordan_rose@apple.com</a>> wrote: </div> <br class="Apple-interchange-newline"> <div class=""> <meta content="text/html charset=utf-8" class=""> <div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""> <br class=""> <div class=""> <blockquote class=""> <div class=""> On Dec 7, 2015, at 19:12, Ling Wang via swift-evolution < <a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote: </div> <br class="Apple-interchange-newline"> <div class=""> <div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"> Besides, we shouldn’t use `final` to denote storage at all for `final` is about inheritability/overridability not about storage. </div> <br class="Apple-interchange-newline"> </div> </blockquote> </div> <br class=""> <div class=""> Please remember that stored properties <i class="">can</i> be overridden in Swift: </div> <div class=""> <br class=""> </div> <blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""> <div class=""> class Base { </div> <div class=""> /*instance*/ var flag: Bool = true </div> <div class=""> } </div> <div class=""> <br class=""> </div> <div class=""> class Sub : Base { </div> <div class=""> override var flag: Bool { </div> <div class=""> didSet { </div> <div class=""> if flag { print("The flag was set!") } </div> <div class=""> } </div> <div class=""> } </div> <div class=""> } </div> </blockquote> <br class=""> <div class=""> This is theoretically possible at the class level as well, but doesn't really make sense for what's currently spelled "static var", since you'd be accessing the same storage in different ways. Does the proposal mean that a stored "type var" is non-overrideable, but a computed "type var" is overrideable, implicitly? </div> <div class=""> <br class=""> </div> <div class=""> Jordan </div> </div> </div> </blockquote> </div> <br class=""> </div> </div> </blockquote> </div> <br class=""> </div> </div> </blockquote> </div> <br class=""> </div> </div> </blockquote> </div> <br class=""> </div> </div> </div> </div> </div> </blockquote> </div> <br class=""> <br><br></div>