3 ms·
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? H
by agentultra 16y ago
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 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.
- epochwolf 16y agoRuby already does this. Modules can include other modules, support public/protected/private members, and have aliasing and conflict resolution (last one included wins)
- ekiru 16y ago> (last one included wins) This is why Ruby doesn't do this. One of the primary purposes of traits is to fix the problem of having to linearize mixins/parents. Aliasing does ease the problems of linearization, but it doesn't solve them all. If in a mixin-based system like Ruby you include two modules which initially have no conflicting methods, but at some point methods are added such that there is a conflict, the conflict is silently ignored. Yes, you should pay attention to changes to the mixins you use, but linearization means that whenever a method is added to a mixin, being certain that your module/class has the right method means going through every single class that uses the mixin and looking at all the other mixins that class uses to ensure that they do not conflict. Traits make changing code easier by doing that checking for you. The one disadvantage is that if you want to ignore a conflict you have to say so, but I don't actually think that is a disadvantage: if a Ruby module says "include Foo, Bar" and both Foo and Bar have an explode method, someone reading the code can't tell if the writer of the code was aware of the two explode methods and chose to use the Bar method, or if they were unaware of the conflict and might have either wanted no explode method or the Foo explode method.
- xentronium 16y agoWhile you're right about that point, there is a reason why conflicts are allowed: inheritance chain ([1] for demo) which provides you a VERY powerful tool for chain-combining traits. [1] http://www.dcmanges.com/blog/20 http://www.dcmanges.com/blog/20
- viraptor 16y agoAgreed. Also the conflict resolution is done in an interesting way. If you have 2 traits that have N conflicting methods, you have to rename all N methods in every single class using the traits (even if it doesn't use the methods in question). Another interesting side effect is that even if you don't use a particular trait, but a conflict appears upstream - boom - "Warning: Trait method hello has not been applied, because there are collisions with other trait methods on TraitsTest in %s on line %d" If I understand it correctly: You will be warned that a collision appeared, NONE of them will be applied and it's only a warning, so it won't stop the execution until you step on the "missing method" trap. Now that's a creative way to shoot yourself in the foot.