UPDATE: I am not alone in my pondering on this issue and it seems it is indeed a bug. See here. The day it is fixed is going to be a fantastic day! :)
This started out as I love PHP traits! I'm going to use them everywhere! ^_^
and now it has turned into a Thought Exercise / Learning Experience >_<
.
Consider the following example:
trait TheErrorOfYourWays{
public function booboo(){
echo 'You had a booboo :(';
}
}
trait SpectacularStuff1 {
use TheErrorOfYourWays;
}
trait SpectacularStuff2 {
use TheErrorOfYourWays;
}
class DoSomethingSpectacular {
use SpectacularStuff1, SpectacularStuff2;
}
This results in (obviously not so obviously):
Fatal error: Trait method booboo has not been applied, because there are collisions with other trait methods on DoSomethingSpectacular.
So my question: How do I resolve method conflicts in traits? Is it possible to achieve overlapping trait "inheritance"? If so, what is the "right" way to do this?
Why I want to do this:
- I want to create self contained traits and classes (mix and match style). If it is at all possible, I want to say "use" and then magic stuff must happen. No having to scratch my head and think, "Now what namespace was that trait in again?", etc, etc.
- No having to edit classes and traits on the fly when I do something "adventurous" and discover I have inadvertently created a conflict.
- Seemed like a good idea at the time.
What I have tried:
- The PHP Manual.
- The Google.
- SO including this question -> Not the correct answer for this scenario.
- Found this but I am using PHP version 5.5.1. It's fixed, right? Right?
-
A fantastic array of "as", aliases, even insteadof, in different places, times, universes, etc. Including, but not limited to:
trait SpectacularStuff1 { use TheErrorOfYourWays{ TheErrorOfYourWays::booboo as booboo1; } } trait SpectacularStuff2 { use TheErrorOfYourWays{ TheErrorOfYourWays::booboo as booboo2; } } class DoSomethingSpectacular { use SpectacularStuff1, SpectacularStuff2 { /* Tried separately, but included here for brevity's sake */ SpectacularStuff1::booboo as booboo3; SpectacularStuff2::booboo as booboo4; } }
AND
use TheErrorOfYourWays as Erroneous1; trait SpectacularStuff1 { use Erroneous1{ Erroneous1::booboo as booboo1; } } use TheErrorOfYourWays as Erroneous2; trait SpectacularStuff2 { use Erroneous2{ Erroneous2::booboo as booboo2; } }
I understand that:
- I can change TheErrorOfYourWays to a class and make booboo() static but I would like to learn about this specific trait behaviour.
- I can remove TheErrorOfYourWays from the traits and use it in the class, but that's hardly "self-contained" then. Everytime I use the traits I have to remember to use TheErrorOfYourWays in the class even if I don't call booboo() directly from the class. Sounds dangerous.
- I have probably made some rookie syntax error or failed to understand aliasing on a profound level. If so, please... explain... slowly...
- There is probably a better way to do this. If so, please... explain... slowly...
- I may be prematurely enthusiastic and PHP doesn't do this yet. Let me down gently.
Thanks!