Hi Rasmus: First, sorry, I don't have currently the time to reiterate all discussions on these questions. Please, do me the favor and search the archives for previous discussions. I believe _all_ points you raise here have been discussed and commented before, and most of them quite recently.
Since I believe the answers are already given, let me try another approach to tackle your problems. From my perspective the purpose of traits is often misunderstood. So, let me ask a few questions. They might sound basic, but I want to better understand your design rational, and the reasons behind your implementation approach. If you got the time, please try to answer all of them. They might seem suggestive, or even worse, 'rhetorical', but that is not on purpose. Answering them will help us all better to understand what the underlying issues/conceptual problems are we need to tackle, either by improving the current implementation and/or documentation. On 11 Nov 2011, at 17:00, Rasmus Schultz wrote: > class Cart > { > public static $instance; > > # public function addItem(CartBehavior $item, $amount=1) // => script > terminates > public function addItem($item, $amount=1) > { > echo "Adding {$amount} {$item->getName()} to shopping cart - price = > ".($amount * $item->getPrice())."\n\n"; > } > } What is the real purpose of adding the type hint for CartBehavior here? My understanding would be, you want to express/document that the given object is required to support a specific set of operations. Is there any other semantics that need to be expressed by this annotation? On a practical level, you probably want to make sure that the engine never barks at you because it got an object that does not understand a certain operation. Is it relevant for the method using that object that it provides a specific implementation for the required set of operations? [Side note for the archive: traits do not guarantee that] > var_dump($test instanceof CartBehavior); // => false Beside testing the corner cases of the language definition, is there any practical need for this test? Do you have an example where it is desirable to know exactly that a particular implementation is provided by an object? > var_dump((new ReflectionClass('Product'))->getTraits()); // CartBehavior is > a ReflectionClass? Well, the reflection API is not perfect yet. Other interesting features, like knowing how conflicts where resolved are missing, too. (I think) The reason for that is unfortunately missing time. > Secondly, the instanceof operator doesn't complain when you test to see if > an object carries a trait - if this isn't going to work, it should at least > throw an exception. You refer to the previous example, I suppose: > var_dump($test instanceof CartBehavior); // => false Why would it be beneficial to throw an exception here? $test is not an instance of CartBehavior, since traits cannot be instantiated, and do not provide any guarantees in what ever respect. So, even if a class uses CartBehavior, you would never be sure that it actually also uses all of the implementations provided by it. > Lastly, when you reflect on a trait, it comes back as an instance of > ReflectionClass. As pointed out, traits are probably more similar to > interfaces than they are to classes, and they definitely don't have > properties, as are exposed by the ReflectionClass type. [Well, it can be useful to test for the properties expected by a trait.] Yes, that is an implementation artifact of how the reflection API is designed. > I would also point out that the examples in the documentation (which it > seems were just copied from the RFC?) do not demonstrate any real purpose > of this feature. Is this the most anybody has attempted to do with this > feature? Trying to come up with a real example, I didn't get very far > before running into these stumbling blocks. I frequently search for usages of traits on the web, and by now, there are quite a number of articles giving examples and discussing the pros and cons of traits. So, no, you are not the first one. But, yes, the current documentation page could use some better examples. > If I can't use instanceof to check for a trait (A), then I would at least > expect to be able to write a trait that implements an interface (B) - does > that not seem reasonable or logical? The discussion we had on that topic evolved to the following proposal: https://wiki.php.net/rfc/horizontalreuse#requiring_composing_class_to_implement_interface However, to my understanding, there was no consent on actually adding this. > Having to use both the interface and the trait as a pair, and having to > explicitly apply them both to the class, feels like a work-around. The discussions we had here suggest otherwise: this is exactly the way to go from a conceptual perspective. It keeps the two concepts apart, avoids confusion, and thus, is the conceptual purer alternative. However, by answering my questions from above, you can certainly make a point that the practical overhead does not justify this conceptual burden. > I apologize if I'm somehow missing the big picture here, or maybe I set my > expectations too high - but my first impression of this feature is that > it's crippled and somewhat half-baked... If there was a deliberate and > logical reason for not supporting these features, I would like to > understand why. If not - great work so far, but perhaps this feature is not > quite mature enough for release just yet? On a personal note: never tell a mother that her child is ugly. Please stay constructive. Thanks! Best regards Stefan -- Stefan Marr Software Languages Lab Vrije Universiteit Brussel Pleinlaan 2 / B-1050 Brussels / Belgium http://soft.vub.ac.be/~smarr Phone: +32 2 629 2974 Fax: +32 2 629 3525 -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php