Another traits implemenation http://php.net/manual/en/language.oop5.traits.php On Apr 21, 2016 5:53 PM, "Niall Young via swift-evolution" < [email protected]> wrote:
> At Tue Mar 1 19:00:21 CST 2016, Brian Pratt brian at pratt.io wrote: > > I feel like the solution to the Arrow/Enemy problem that best fits with >> Swift's current available tools is neither a protocol (which, as you >> mentioned, doesn't get rid of the initialization/configuration of the >> member data) or inheritance (which, as you mentioned, can only have one >> base type) -- it's to extract a third type that handles >> > > What you're describing sounds _exactly_ like Traits :-) > > http://scg.unibe.ch/research/traits > > Traits could be a peer of extensions, filling a niche that isn't quite the > same niche as a default implementation, but it could be consistently and > safely consumed like an extension, with its own rules of consumption > (flattening) - to implement any need or explicit protocol requirement that > a Class, Value Type or Protocol has at compile-time. > > Think of a Trait as providing a consumable set of functions. Now imagine > that we're combining the collective declarations of 1..N Traits all > together, consumed by a Class or Value Type (or Protocol!) in a predicable > and safe way (flattening: see the first Traits white paper). > > i.e. we get the same result regardless of the order of consumption, how > many times any given Trait(s) were consumed, Traits dependent on other > Traits etc. Predictable results, given the same input we always get the > same output. This is flattening, but read the white papers for more detail. > > The process of flattening itself could be a peer of the existing rules > around static dispatch vs. dynamic dispatch around > default-implementations/extensions vs. class overrides. > > A Trait declaration could look something ~like: > > trait TraitX (ProtocolAdherenceY): DependentTrait1, > DependentTrait2 { > > private var foo > private let bah { .. } > > func fooify { .. } > mutating func bahify { .. } > private func hah { .. } > > } > > with a Trait being a closure, where _only private_ data Properties can be > declared, providing 1..N function implementations. It could conform > _towards_ a Protocol (partial to full conformance), and also be dependent > upon other names Traits, which would be consumed in parallel as a > first-class citizen with the Trait that depends on it. > > Traits could be consumed by a class or value type, to provide function > implementations which could be satisfying a Protocol implementation > requirement, along with its own private functions and private data for its > (private to Trait) local state etc. The consumption syntax I'm still > unsure of, but a clear declarative "flattens Trait1, Trait2, .. , TraitN" > or similar would do. > > The consuming Class or Value Type would remain fully responsible for its > own Protocol conformance, and if any of the consumed Trait public > implementations conflict or overlap with each other, then the conflicts > must be resolved explicitly by the Class or Value Type itself, where it is > consumed. > > The resulting "flattened" set of Traits would be input towards the Type's > own compiler requirements, with the author being required to explicitly > resolve any and all conflicts at compile-time. Cconsumption at run-time > could be a later feature as Swift's core stabilises and specific run-time > metaprogramming facilities are exposed. > > Explicit conflict resolution, via a flattened 2D matrix of Trait:func > identifying conflicts that need to be resolved by the consumer, also gives > reliable results with no cognitive overhead as Brian's identified in > resolving Mixin consumption. Plus there is no diamond-problem, as there is > no inheritance. With Traits, it _must_ be resolved explicitly in code, > with suitable compiler errors for malformed Types that have consumed 1..N > Trait(s). > > Stateful Traits suggest that as long as the data is private _to the Trait_ > then we can safely ignore some of the complexity of state in Traits - it > just isn't exposed as the Trait declaration itself is a closure. > Dependency on state in the consumer could proxy to > class/instance/value-type data via Protocol. > > Swift and Protocols seem like a perfect match for "capital-T" Traits. Any > thoughts on if this is suitable for a 3.0 or 4.0 Proposal? > > I've recently built similar mechanisms exploring these concepts with basic > metaprogramming and a common root class in a dynamic language, but as a > core language feature of Swift I think it could very much complement the > existing protocols and extension concepts, with 1..N re-usable > implementations, and it also could help to resolves the uncertainty/rules > around static vs. dynamic dispatch: static could remain the domain of > extensions / default implementations; with dynamic dispatch available to > Classes and Traits? > > More Reading: > > http://scg.unibe.ch/research/traits > > Cheers, > > -- > Niall Young > [email protected] > > > At Tue Mar 1 19:00:21 CST 2016, Brian Pratt brian at pratt.io wrote: > > I think this sort of composition is preferable to inheritance in a lot of >> ways, and Swift has some built-in tools that can augment it: a robust >> protocol and extension system, a type constraint system that allows for >> lots of flexibility at compile-time, etc. >> >> Mixins (and in general, the sharing of code primarily via inheritance) >> tend >> to create large objects with lots of responsibilities, and that tends to >> bloat APIs as you need to either pick extremely specific names to avoid >> collisions, or worse, keep the cognitive overhead of "shoot, what is this >> method aliased to again?" in your head all the time. If something *is* >> both >> an A and a B, it needs to act like (and speak the same language of) an A >> or >> a B *all* of the time. >> >> Beyond this, I think it's going to be extremely complex managing >> compile-time type constraints with renames in place. Let's say I have a >> class C that inherits from bases A and B, which implement protocol P and Q >> respectively, and there's a naming collision. Functions that expect Ps or >> Qs will have to know about the renaming of conflicts from the combination >> of A+B? Unless I'm missing something, it feels like this complexity would >> continue to spread out to all sorts of collaborators, when the current >> system isolates it much more effectively. >> > > I think protocols and protocol extensions (mixed with lots of composition) >> is a better scenario than abstract classes or multiple inheritance, and >> therefore, I'm still a -1 on mixins in Swift (strictly on principle; this >> proposal actually argues the case very well). >> >> - Brian >> > > And agreed Thorsten!: > > Unfortunately the current discussions about Mixins, abstract classes, POP >>> vs. OOP suffer from having forgotten achievements of the past which >>> results >>> in creating differences where none should be. >>> >> > It is unfortunate and IMO just for historical reasons that there is a >>> dichotomy between protocols and classes at all instead of having just >>> classes with multiple inheritance done right (and abstract methods). >>> >> > - We should extend protocols to support real multiple inheritance with >>> renaming >>> >> > -Thorsten >>> >> _______________________________________________ > swift-evolution mailing list > [email protected] > https://lists.swift.org/mailman/listinfo/swift-evolution >
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
