| I don't understand the vernacular. One of the noteworthy language additions are Traits – a brand new horizontal code reuse mechanism. Code re-use mechanism? Horizontal? I didn't realize PHP was so geometric. What an interesting concept. While traits are technically different from mixins – they are both designed to fill the same gap left by a single-parent inheritance model So let me try and get this straight: mixins fill a gap left by a single-parent inheritance model and so traits are like mixins because PHP has a single-inheritance model but traits are technically different in some way? This is getting confusing... Python, Perl, Ruby, and many languages with multiple inheritance have been using mixins for... well a long time. It's pretty straight forward. Perl5 got "roles" through Moose and Perl6 has them natively. I think they're explanations are a little more clear. (http://search.cpan.org/dist/Moose/lib/Moose/Manual/Roles.pod) As the original author of the patch Stefan Marr pointed out – traits are nothing more but a compiler assisted copy and paste. In true PHP fashion! What an interesting way to think about it. Conflicts and Aliases Ok, this is pretty cool. It's an edge case, but there's already a solution. Neat. Oh... wait a second, I think I've found the meat of it: Trait method definitions support all modifiers just like regular class methods do – that includes visibility modifiers, final, static and abstract. The latter can be used to define abstract methods expressing requirements for this particular trait So this is how they're slightly different than regular-old classes? By being able to use all the same keywords as regular old classes? It seems that the meat of it is at the very end: Traits only take part in the process of building a class and do not add any new run-time semantics. That means that usual PHP object-oriented functionality (like late static bindings) work as expected when combined with traits. But this next one is a bit of a gotcha: Traits can be composed from other traits (the same way classes use traits). Wait... what? Why would you want to do this? You're just getting back into hierarchies again... and pretty much just working around multiple-inheritance without calling it such. It's good to see PHP is evolving. Most people still think of PHP4 and shudder (and rightfully so). Evolving means it might be catching up to the superior languages it competes with in the web space. (Note the tongue-in-cheek). I'm still not convinced, but it's a step forward I am sure for PHP programmers everywhere. Just don't actually use trait-inheritance and you should be fine. |
It indeed seems like that ;-)
There are four concepts here:
* Multiple inheritance
* Interfaces (abstract types)
* Mixins
* Traits
Multiple inheritance is available in languages like C++ and Python. But multiple inheritance has well known highly problematic side effects that resolve around diamond inheritance and method aliasing. Basically you have a directed graph of parent classes (with diamonds and all) all implementing a foo() method, and then have to pick a method of linearizing that graph to find out which method actually wins if someone calls o.foo(). There are multiple solutions to that, but all are non-intuitive and have caused heaps of trouble. It's just way to hard for a programmer to reason which method will be called in his program.
This is why Java did away with multiple inheritance and just has interfaces. A lot simpler, a lot cleaner, and easy to understand, but sadly lacking in functionality.
The problem is supposed to be fixed by traits and mixins. I think there is no really clean demarcation between the two. My understanding is that traits are more or less mixins, but with the aliasing features and similar stuff you highlight.
The traits are nothing more but a compiler assisted copy and paste is actually a feature, not a bug. This is exactly what you actually want to keep your program understandable: the code/functionality from traits is effectively treated as copied into your class, and there is exactly one "winner" in the race to be the "foo()" method for this class, where the winner is determined by things like aliasing, or order. All the weird situations where parent classes call a method that is overridden in some branch of the inheritance graph just don't occur.
So traits/mixins are IMHO a huge step forward from multiple inheritance or just interfaces. Not that this will help with the mess that is PHP much ...