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

Reply via email to