Hi Larry, > It sounds interesting to me, and I can definitely see the value. I think I'd > suggest having multiple included traits override each other, however, so > that: > > trait A { > function foo() { echo "A"; } function bar() { echo "A"; } > } > trait B { > function foo() { echo "B"; } function bar() { echo "B"; } > } > class C { > use A; > use B; > } > $c = new C(); > $c->foo(); // prints "B" since that came second. $c->bar(); Lets suppose you will need here the "A" for some domain specific reason. This is not possible with this mixin semantics, with traits it is.
> That said, the conventional OOP mechanism to get the same result would, I > think, look something like this: > > interface iface { > function foo(); > function bar(); > } > > class I implements iface { > function foo() { ... } > function bar() { ... } > } > > > class A implements iface { > protected $iface; > > function __construct() { > $this->iface = new I(); > } > > function foo() { return $this->iface->foo(); } > > function bar() { return $this->iface->bar(); } > } > > The class/interface method takes a little more typing and an extra function > call on the stack, but otherwise what is the advantage of Traits over this > method? (Really, I'm genuinely curious.) Yes, it is the typical delegation pattern. Often used to achieve code reuse without the need to inherited and clutter up interfaces with unnecessary stuff. The advantage of traits here is the preservation of the encapsulation property of your classes. In many situations you would need to propagate some state to the delegate which is not a nice thing in all situations. Instead it would be more elegant to have a method in the class to preserve encapsulation. The method could be provided by copy and past, or for consistency and conceptual reasons, by a trait :) > You also note that this mechanism has no runtime impact. That's unfortunate, > because I'd find the ability to add methods to an object at runtime > conditionally based on some other value far more useful in my work. :-) > Especially since, as above, there seems to be a way to implement this > functionality now as-is with a little more typing, yet runtime modification > is still impossible without eval() and similar scary stuff. > > Vis, I'd find the following more useful in the code I write: > > trait Baby { > function crawl() { ... } > } > > trait Teen { > function complain() { ... } > } > > class Person { > protected $age; > function __construct($age) { > $this->age = $age; > if ($this->age <= 3) { > $this->addTrait('Baby'); > } > if ($this->age >=13 && $this->age <=19) { > $this->addTrait(Teen'); > } > } > } > > $p[1] = new Person(19); > $p[1]->complain(); > > $p[2] = new Person(1); > $p[2]->crawl(); > > foreach ($p as $person) { > if ($p instanceof Teen) { > $person->complain(); > $person->parent->ground($person); > } > } > > > I don't know if that's technically not feasible or technically not a Trait > anymore and therefore off topic in this thread (if it is, that's fine, let me > know and I'll shut up about it <g>), but that strikes me as more useful than > just runtime composition. This is not Traits anymore, yes :) and as Rasmus suggests there would be definitely some problems. But you might be interested in Context-oriented Programming, it tries to solve such crosscutting concerns you've described in an dynamic way. Unfortunately I've no code example at hand but you could have a lock at http://www.swa.hpi.uni-potsdam.de/cop/ ContextR for Ruby is very promising to solve such problems. I've had a thought on this for PHP, too. But think there would be many people against something like "dynamic behavior" even if this looks like an oxymoron ;) Kind Regards Stefan -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php