[swift-evolution] Properties on Default Protocol Implementations

Howard Lovatt howard.lovatt at gmail.com
Sun Jan 10 23:03:28 CST 2016

I suspect it is easier both for the compiler and the programmer to allow
abstract classes and abstract functions within abstract classes than
allowing extensions and by extension (pun intended) protocols to have
stored properties. There is precedence for this approach, in Scala and
Java you can have their equivalents of calculated properties in protocols
but not stored properties. Both Scala and Java have abstract classes and
this seems to work well.

On Monday, 11 January 2016, Douglas Gregor via swift-evolution <
swift-evolution at swift.org> wrote:

> On Jan 10, 2016, at 6:43 PM, Wallacy via swift-evolution <
> swift-evolution at swift.org
> <javascript:_e(%7B%7D,'cvml','swift-evolution at swift.org');>> wrote:
> Thinking about some problems presented here this mailing list. I believe
> that by following the same concepts behind the default protocol
> implementations, allowing the same mechanism to provide default properties
> can be a remarkable gain for language.
> Rationale:
> It has been proposed here also on this list, a need to produce abstract
> classes, one of the reasons that need, is because is not possible to
> declare properties in the same way as we declare default implementation on
> protocols.
> I also believe that this can help in the concept of multiple inheritance,
> and serve as an aid to the default implementation on protocols, and
> "complete" the Protocol-Oriented Programming concept.
> For example:
> protocol Named {
>     var name: String { get }
> }
> protocol Aged {
>     var age: Int { get }
> }
> struct Person: Named, Aged {
>     var name: String
>     var age: Int
> }
> extension Aged where Self: Named {
>     func wishHappyBirthday() { // regular default implementation
>         print("Happy birthday \(self.name) - you're \(self.age)!")
>     }
>     var birthdayVideo: AVPlayerItem? // nil is a default value
> }
> ...
> func playBirthdayMediaFrom(person: Person){
>     var avPlayer = AVPlayer(playerItem: person.birthdayVideo)
>     // etc...
> }
> One of thousands of using this feature is to prevent us to create
> variables that are not actually part of the data model we are shaping.
> birthdayVideo in this case would be any variable that is not part of our
> model, but need to be associated with the object (or structure) in some
> context of our application. (And not be used anywhere else in the APP or
> another API).
> Other examples maybe a counter helper, weak reference to something, etc.
> There is a infinite examples when we need to declare some variable just to
> make the "api" happy like add a observer, holding some value, and use this
> again to removeobserver in dealloc.
> I believe that the same rules and the same mechanisms involving default
> implementation functions, should govern this default property
> implementation, and any discussion about it on the problems on protocols
> rules should be made separate this thread.
> 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.
> 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.,
> struct MyStruct { }
> extension MyStruct { var storage: Int = 0 } // error: extensions may not
> contain stored properties
> class MyClass { }
> extension MyClass { var storage: Int = 0 } // error: extensions may not
> contain stored properties
> 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.”
> 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.
> 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).
> 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.
> 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:
> * Only allow them on class-bound protocols, where there is a reasonable
> implementation model
> * 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).
> Either handles the example brought up in the discussion of abstract base
> classes.
> - Doug

  -- Howard.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160111/58e93443/attachment.html>

More information about the swift-evolution mailing list