<div dir="ltr">You are not alone, discursions like start a long time ago on Swift 1.1 on the old forum.<div><br></div><div>I also have here on my desktop some proposals involving storage properties in protocols.<br></div><div><br></div><div>The idea appears to be simple, but is hard to get a good design.</div><div><br></div><a href="http://thread.gmane.org/gmane.comp.lang.swift.evolution/2996">Properties on Default Protocol Implementations</a><br><br>Some quotes that can help here:<div><br></div><div>-- <span style="color:rgb(0,0,0);font-family:arial,sans-serif;font-size:medium;line-height:normal">Douglas Gregor</span><span style="color:rgb(0,0,0);font-family:arial,sans-serif;font-size:medium;line-height:normal">  -- </span>&quot;</div><div><div style="color:rgb(0,0,0);font-family:arial,sans-serif;font-size:medium;line-height:normal">Default implementations of functions don’t require per-instance state, while adding a stored property via a protocol extension does. Let’s step back to a simpler problem: stored properties in (non-protocol) extensions.</div><div style="color:rgb(0,0,0);font-family:arial,sans-serif;font-size:medium;line-height:normal"><br class=""></div><div style="color:rgb(0,0,0);font-family:arial,sans-serif;font-size:medium;line-height:normal">In the existing language, one can only introduce stored properties in the primary definition of the type. That’s because, when we create an instance of that type, we need to know how much storage to allocate for that instance. So, right now, we don’t even allow, e.g.,</div><div style="color:rgb(0,0,0);font-family:arial,sans-serif;font-size:medium;line-height:normal"><br class=""></div><div style="color:rgb(0,0,0);font-family:arial,sans-serif;font-size:medium;line-height:normal"><span class="Apple-tab-span"></span>struct MyStruct { }</div><div style="color:rgb(0,0,0);font-family:arial,sans-serif;font-size:medium;line-height:normal"><span class="Apple-tab-span"></span>extension MyStruct { var storage: Int = 0 } // error: extensions may not contain stored properties</div><div style="color:rgb(0,0,0);font-family:arial,sans-serif;font-size:medium;line-height:normal"><br class=""></div><div style="color:rgb(0,0,0);font-family:arial,sans-serif;font-size:medium;line-height:normal"><span class="Apple-tab-span"></span>class MyClass { }</div><div style="color:rgb(0,0,0);font-family:arial,sans-serif;font-size:medium;line-height:normal"><span class="Apple-tab-span"></span>extension MyClass { var storage: Int = 0 } // error: extensions may not contain stored properties</div><div style="color:rgb(0,0,0);font-family:arial,sans-serif;font-size:medium;line-height:normal"><br class=""></div><div style="color:rgb(0,0,0);font-family:arial,sans-serif;font-size:medium;line-height:normal">because, in the worst case, we don’t know about the storage required for the “storage” property until after we’ve allocated some instances of MyStruct or MyClass, and we can’t simply go back and resize those instances when we learn about the “storage” property. The “worst case” here could come about with shared libraries: put the MyStruct/MyClass primary definitions into an app, then put the extensions into a separate shared library. The app creates some MyStruct and MyClass instances, then loads the shared library, and now we have a problem: those instances have no storage for “storage.”</div><div style="color:rgb(0,0,0);font-family:arial,sans-serif;font-size:medium;line-height:normal"><br class=""></div><div style="color:rgb(0,0,0);font-family:arial,sans-serif;font-size:medium;line-height:normal">We could relax the requirement to allow extensions in the same module as the primary definition of that type to introduce stored properties, because they’re compiled along with the primary type definition anyway. This doesn’t solve out-of-module extensions, of course.</div><div style="color:rgb(0,0,0);font-family:arial,sans-serif;font-size:medium;line-height:normal"><br class=""></div><div style="color:rgb(0,0,0);font-family:arial,sans-serif;font-size:medium;line-height:normal">We could embed a pointer into each instance that points off to the stored properties for that instance. The pointer would refer to some lazily-allocated memory on the heap with that extra storage. However, this would either bloat every data structure by a pointer (including “Int”!) or have to be opt-in, neither of which are great. I don’t think there is any reasonable implementation for out-of-module stored properties in extensions of value types (struct/enum).</div><div style="color:rgb(0,0,0);font-family:arial,sans-serif;font-size:medium;line-height:normal"><br class=""></div><div style="color:rgb(0,0,0);font-family:arial,sans-serif;font-size:medium;line-height:normal">For classes, where we have object identity, we could have a side table containing the stored properties (keyed on the object’s address). This is how Objective-C’s associated objects work, and it’s a reasonable module for out-of-module stored properties in extensions of classes.</div><div style="color:rgb(0,0,0);font-family:arial,sans-serif;font-size:medium;line-height:normal"><br class=""></div><div style="color:rgb(0,0,0);font-family:arial,sans-serif;font-size:medium;line-height:normal">Getting back to stored properties in protocol extensions, the general feature isn’t implementable without having some mechanism for out-of-module stored properties in extensions of structs and enums, so you can limit it in a few ways:</div><div style="color:rgb(0,0,0);font-family:arial,sans-serif;font-size:medium;line-height:normal"><br class=""></div><div style="color:rgb(0,0,0);font-family:arial,sans-serif;font-size:medium;line-height:normal"><span class="Apple-tab-span"></span>* Only allow them on class-bound protocols, where there is a reasonable implementation model</div><div style="color:rgb(0,0,0);font-family:arial,sans-serif;font-size:medium;line-height:normal"><br class=""></div><div style="color:rgb(0,0,0);font-family:arial,sans-serif;font-size:medium;line-height:normal"><span class="Apple-tab-span"></span>* Allow them as default implementations within a protocol (not an extension of a protocol!); a type can conform to that protocol either by providing its own implementation of that property or somewhere where it is reasonable for the default implementation to inject a stored property into that context (e.g., on the primary type, within the same module as the primary type, or on a class).</div><div style="color:rgb(0,0,0);font-family:arial,sans-serif;font-size:medium;line-height:normal"><br class=""></div><div style="color:rgb(0,0,0);font-family:arial,sans-serif;font-size:medium;line-height:normal">Either handles the example brought up in the discussion of abstract base classes.</div><div style="color:rgb(0,0,0);font-family:arial,sans-serif;font-size:medium;line-height:normal"><br class=""></div><div style="color:rgb(0,0,0);font-family:arial,sans-serif;font-size:medium;line-height:normal"><span class="Apple-tab-span"></span>- Doug</div></div><div>&quot;<br><div><br></div><div>-- <span style="color:rgb(0,0,0);font-family:arial,sans-serif;font-size:medium;line-height:normal">Chris Lattner</span><span style="color:rgb(0,0,0);font-family:arial,sans-serif;font-size:medium;line-height:normal">  -- </span>&quot;</div><div><pre style="color:rgb(0,0,0);line-height:normal">Hi Doug,

Have you considered this similar-but-different approach?

- Allow extensions on classes (only) within the same module/resilience domain as the class to add stored
properties. This would keep them inline in the instance.
- Allow protocols to have stored property declarations, introducing a new “protocol with storage”
(PwS) concept.
- Classes can directly conform to a PwS in its definition, or within an extension inside the same
module/resilience domain.

Just this would give many of the benefits of a full mix-in programming model.  People could define these
protocols, and their local implementation of the type can benefit from them.  It doesn’t support
retroactive mixin’ing, but that is probably a good thing.  I’m assuming that we don’t want to allow
adding state to structs within a resilience domain, just because I don’t think that is actually a good
thing to add to the programming model (other reasonable people will surely disagree).

This base model could then be extended:
- Structs could conform to a PwS in their definition, but not an extension.  We could optionally require the
struct to redeclare the properties to improve readability of the struct, but it wouldn’t be required
from an implementation perspective.
- Classes could conform to a PwS across resilience boundaries, but wouldn’t get the state: they’d have
to implement the storage requirement with a computed property.
- We could introduce an “associated objects” property behavior that makes providing the computed
property very straight-forward, using the out of band implementation approach of ObjC.

The advantages of this approach I see are:

1) implementable, always a bonus.
2) keeps predictable performance.  You don’t get out “associated objects” overhead unexpectedly. 
All state is always stored inline.
3) retroactive mixins are possible, but explicit.

The primary downside of this approach is that it introduces yet another weird protocol variant with
limitations and behaviors, making the model more complicated.

-Chris</pre></div><div>&quot;</div><div><br></div><div><div>Some of the challenges I&#39;m having to write my proposal is to find a model that does not make the language much complex and still bring a direct benefit.</div></div><div><br><div class="gmail_quote"><div dir="ltr">Em sáb, 27 de fev de 2016 às 06:59, Антон Жилин &lt;<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>&gt; escreveu:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Some people opposed to Abstract Classes proposal (including myself) have said that mixins could solve the problem better.<div>So I prepaired a proposal draft to add stored properties to protocols. Here it is:</div><div><a href="https://gist.github.com/Anton3/f0550922c1be0fc5447c" target="_blank">https://gist.github.com/Anton3/f0550922c1be0fc5447c</a><br></div><div><br></div><div>P.S. I added a `mixin` keyword in the beginning, but we can opt to just extend protocols, which I mention in &quot;alternatives&quot;.</div></div>
_______________________________________________<br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br>
</blockquote></div></div></div></div>