[swift-evolution] Properties on Default Protocol Implementations

品雪 pinxue at gmail.com
Mon Jan 11 01:00:38 CST 2016

I prefer Ruby's module mixing over Java's long inheritance path
(AbstractBase <|= Abstract <|= DefaultBase <|= ...).

In objc, non-fragile instance variables already allow changing base
class without re-compiling sub class, it should not be that hard to
support this feature. And I agree it is better not allowed for struct
in Swift because of semantic of value type.

On Mon, Jan 11, 2016 at 1:37 PM, Douglas Gregor via swift-evolution
<swift-evolution at swift.org> wrote:
> On Jan 10, 2016, at 9:03 PM, Howard Lovatt <howard.lovatt at gmail.com> wrote:
> 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.
> Developers independently want the ability to add stored properties in
> extensions (at least for classes). The delta from that to stored properties
> as default implementations in protocols isn’t that large, and if it’s a
> better modeling of the problems abstract classes are meant to solve, that’s
> the right thing to do. Other than stored properties, what important problems
> do abstract classes solve that protocols don’t?
> 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.
> Numerous languages have abstract classes; the question is whether they are
> the right answer in Swift.
> - Doug
> 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> wrote:
>> TL;DR
>> 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.
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

Best Regards!

Yang Wu
Location: Pudong, Shanghai, China.
EMail    : pinxue at gmail.com
Website: http://www.time2change.mobi http://rockplayer.com
Twitter/Weibo : @pinxue

More information about the swift-evolution mailing list