[swift-evolution] [Draft] Mixins

Simon Pilkington simonmpilkington at icloud.com
Tue Mar 1 23:24:01 CST 2016


Increasingly I am finding that in almost all cases composition provides a better alternative to inheritance. In the case of sharable logic, that logic is better provided as its own complete class with something like the delegate pattern or callbacks if extensibility is required. This encourages small classes with limited responsibility that can be easily/independently tested. 

So with that in mind, the problem I see with this proposal is that it introduces syntactical and conceptual complexity to the language - in particular providing a mechanism to resolve cases of the diamond problem, ordering of init/deinit etc is going to make the usage non-trival - without having a substantive benefit outside of what can be achieved more robustly with the existing constructs - such as protocols - the language provides.

For the examples for mixins presented so far, I’d be interested in understanding why they couldn’t be solved with the existing language and design patterns.

-Simon


> On 1 Mar 2016, at 8:15 PM, Andrey Tarantsov via swift-evolution <swift-evolution at swift.org> wrote:
> 
> +1 (but see below)
>  
> Example:
>  
> My custom Swift notification system currently has two problems that would be solved by mixins:
>  
> 1. Anyone conforming to StdEmitterType has to provide “public var _listeners = EventStorage()", which is obvious non-ideal (I have an Xcode snippet for that).
>  
> 2. I have EmitterType protocol that defines the publish/subscribe contract, and StdEmitterType protocol that provides a standard implementation of the publish/subscribe methods using a stored _listeners property (provided by the conforming class/struct as described in #1). The distinction between EmitterType and StdEmitterType is confusing when both are called protocols, because StdEmitterType is really a mixin. Calling EmitterType a protocol and StdEmitterType a mixin would clear up the confusion.
>  
> Because of reason #2, I'm strongly in support of using a separate keyword.
>  
>  
> I do feel, however, that maybe this isn't a single problem, but instead two orthogonal problems that could have separate solutions:
>  
> 1) Go-style embedding, where a struct's members become the members of its containing struct/class
>  
> 2) an “implicit delegate” facility that allows a struct (you may call it a “mixin”) to access the self of its container, and to impose requirements on the container (funcs/vars that the container has to implement)
>  
> #1 is useful without #2 — the logging example doesn't need anything from it container, it just wants to add a variable
>  
> #2 is useful without #1 — I have other mixin-like examples that benefit from being included (a) in multiple copies, and/or (b) non-anonymously (with a meaningful name), and/or (c) privately.
>  
>  
> Examples of #2 without #1:
>  
> — I have an activity system in my app that tracks the progress and completion of a tree of long-running operations (think a Make-like build process, or an IDE-style code analysis consisting of multiple steps operating on multiple files). The relevant state management and notification logic is encapsulated as ProcessorImpl mixin-like class that tightly binds to its host via an initialization method:
>  
>        public func initializeWithHost<Host: EmitterType>(host: Host, performs performMethod: (Host) -> (Request, OperationContext) -> Promise<Void>)
>  
>    ...some classes perform multiple kinds of processing, so they end up creating multiple ProcessorImpl's; and even for those classes that use only one instance, it is helpful to give it a name (private let analysisState = ProcessorImpl()) and to keep it private (it is manually published via a separate property that has a protocol type)
>  
> — my current Delayed class that implements something similar to performSelector:afterDelay: / cancelPerformSelector in Objective-C, or to function throttling/unbouncing in JavaScript. It has to be a class, because it contains mutable state that is modified from within dispatch_async. Would be great for it to instead be a mixin that would use the “self” of its container, without creating a separate object.
>  
>  
> Thoughts?
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160301/3d6b7a3e/attachment.html>


More information about the swift-evolution mailing list