On 25/02/2008, Stefan Marr <[EMAIL PROTECTED]> wrote:
> Hi,
>
>  there is a lot of discussion going on about how traits should actually
>  work in PHP.
>
>  Currently, one of the main challenges seams to be to agree on a suitable
>  mechanism to avoid breaking traits and there behavior.
>  Eventually, there seams to be a large discomfiture on the excluding of
>  methods and the interweaving of methods from different traits.
>
>  I can agree on the opinion, that a unconditional exclude mechanism could
>  accidentally break traits.
>  But, I really do like the notion to be able to interweave traits and
>  compose something new from it, which results in an overlapping construct
>  using the appropriate methods for a concrete problem. Well, this implies
>  traits are not units of black-boxed reuse. They do act really
>  fine-grained and will require the knowledge about the used methods.
>
>  Therefore, remove/exclude is bad, we need to get rid of it.
>  There are some thoughts about aliasing. It seams to be not the
>  natural/closest solution. Renaming semantics would be more natural, but
>  it implies an exclude of the old method, too. Thus, renaming could
>  accidentally breaking a trait. Eventually, renaming needs to be avoided,
>  too.
>
>  Ok, lets get a step back and recall what traits have to achieve.
>
>  Traits try to be a construct to allow the reuse of a group of semantical
>  related methods.
>  They do not try to replace inheritance or the delegation patter. They
>  are still valid means to reuse "complex behavior and state" things.
>  Instead, the way to go with traits should be to reuse a small,
>  predominantly independent (but semantically related) number of methods
>  not justifying to build a full fledged class from them. Use traits to
>  build a class from them, which adds some additional semantics/behavior
>  to the set of methods got from the traits and build a complete blue
>  print for objects from it.
>
>  The main thing here seams to be that the current proposal does not
>  fulfill the claim to combine the traits properly in the case of
>  conflicts. Instead, there is a lot of potential to break the traits
>  behavior.
>
>  Let's try to find a notation where the traits are combined and conflicts
>  are solved upfront, before being applied to the class. (This is even the
>  way the implementation works right now.)
>
>  To get rid of exclude and rename I would like to propose the following:
>
>  //Example from the RFC with the cross-over conflict to be solved
>  trait A {
>    public function smallTalk() {
>      echo 'a';
>    }
>    public function bigTalk() {
>      echo 'A';
>    }
>  }
>
>  trait B {
>    public function smallTalk() {
>      echo 'b';
>    }
>    public function bigTalk() {
>      echo 'B';
>    }
>  }
>
>  //here the new notion of combing traits and resolving conflicts upfront
>  class Talker {
>    use A, B {
>       B::smallTalk instead A::smallTalk;
>       A::bigTalk instead B::bigTalk;
>       A::bigTalk as talk;
>     }
>   }
>
>
>  The new ``use`` is defined as use with a list of traits to be included
>  into the class.
>  Since the exclude is not appropriated, conflicts could be solved a lot
>  more explicitly with the new ``instead`` keyword.
>  It has be read as: use B::smallTalk instead of A::smallTalk, which
>  solves the conflict explicitly and avoids the need for an exclude
>  operator with the power to exclude arbitrary methods.
>  If more traits are combined it could look like ``A:foo instead B::foo,
>  C::foo;``
>
>  To be able to reuse a method which is excluded this way the ``as``
>  keyword can be used.
>  Read it like this: use A::bigTalk as talk in the class.
>
>  Think with this, it is not possible to remove a method somehow.
>  This could be even superior to the "hidding" thing and the notion of
>  "trait-local" methods since everything/any part of the semantics is
>  explicitly available in the notation. This has not been the case for
>  other notations so far. The trait-local things are nice, but complex and
>  I would prefer to avoid them, since the proposed traits have a very
>  clean and simple semantics. May be we could introduce them as addition
>  in a later release.

I like this mechanism. This really does seem to be what I would use.
It also treats developers with a bit of respect that they understand
what they are doing and as such doesn't need to provide a wasteful
safety net. No magic.

A question though (and I don't have any sort of examples to explain
this better, so I hope you all follow).

If there are common names to methods in multiple traits (assume third
party libraries), and you one trait::method over another (A::bigTalk
instead B::bigTalk;),  this will surely break the b trait? B trait may
well use its own bigTalk method. Instead it is going to end up using
A's bigTalk.

A "way" (more of an idea than a real solution and the syntax is wild
here) would be to support a "namespace" concept.

trait DTalker {
 function dTalk() {
  echo 'D';
 }
}
trait CTalker requires DTalker {
 function cTalk() {
  $this->dTalk();
}
class Talker {
  use ATalker as A, BTalker as B, CTalker
  function usingTraits() {
    $this->A::bigTalk();
    $this->B::smallTalk();
    $this->CTalker::cTalk();

    // Maybe these are all the same method.
    $this->CTalker::DTalker::dTalk();
    $this->CTalker::dTalk();
    $this->dTalk();
  }
 }

Traits as namespaces would solve the issue of conflict in the class
Talker (you would have to explicitly say which trait the method came
from.

I don't know if this can all be resolved at compile time. Surely the
use of call_user_func() and others would impact somehow.

If trait C requires trait D, then this may lead to longer namespaces -
but from my understanding the purpose of namespaces is to resolve
collisions, so it cannot be avoided when there are collisions. (Though
my example doesn't collide - but that's not the point).

I hope this makes some sense.

Richard.


-- 
-----
Richard Quadling
Zend Certified Engineer : http://zend.com/zce.php?c=ZEND002498&r=213474731
"Standing on the shoulders of some very clever giants!"

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to