# RFC: Traits for PHP

- Thread: https://externals.io/message/35562
- Original archive: https://news-web.php.net/php.internals/35562
- Started by php@stefan-marr.de on 2008-02-18T19:27:00+00:00
- Messages: 131
- Page 1 of 6: messages 1 to 25 (25 per page, add `?page=N` to the URL)
- Next page: https://externals.io/message/35562.md?page=2
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #35562 — php@stefan-marr.de — 2008-02-18T19:27:00+00:00

URL: https://externals.io/message/35562#35562

Hi,

during last six months I've studied a language construct called Traits.
It is a construct to allow fine-grained code reuse and in my opinon
this would be a nice feature for PHP, which I did like to propose here.
The following RFC deals with the questions what Traits are, how they are
used, why they are usefull and how they do look like in PHP.
A patch implementing this new language construct is available, too.

Thank you for your attention and I'm looking forward to hear your comments
:)

Kind Regards
Stefan



Request for Comments: Traits for PHP
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

:HTML: http://www.stefan-marr.de/artikel/rfc-traits-for-php.html

... contents::

This RFC will discuss at first the motivation for Traits describing the
rationals
and presenting a short real world use case. The main part will describe the
concept of Traits in detail using the syntax for Traits implemented in a
patch
which is part of this proposal. In the end, the URL of the patch and 
additional resources about Traits are given.

Introduction
============

*Traits* is a mechanism for code reuse in single inheritance languages such
as PHP. A Trait is intended to reduce some limitations of single inheritance
by enabeling a developer to reuse sets of methods freely in several
independent
classes living in different class hierarchies.
The semantics of the combination of Traits and classes is defined in a way,
which reduces complexity and avoids the typical problems associated with
multiple
inheritance and Mixins.

They are recognized for their potential in supporting better composition
and reuse, hence their integration in newer versions of languages 
such as Perl 6, Squeak, Scala, Slate and Fortress.
Traits have also been ported to Java and C#.


Why do we need Traits?
----------------------

Code reuse is one of the main goals that object-oriented languages try to
achieve
with inheritance. Unfortunately, single inheritance often forces the
developer
to take a decision in favor for either code reuse *or* conceptual clean
class
hierarchies. To achieve code reuse, methods have either to be duplicated or
to be moved near the root of the class hierarchy, but this hampers
understandability and maintainability of code.

To circumvent this problems multiple inheritance and Mixins have been
invented.
But both of them are complex and hard to understand. PHP5
has been explicitly designed with the clean and successful model of Java in
mind: single inheritance, but multiple interfaces. This decision has been
taken
to avoid the known problems of for example C++.
Traits have been invented to avoid those problems, too. They enable designer
to build
conceptually clean class hierarchies without the need to consider code reuse
or
complexity problems, but focusing on the real problem domain and
maintainability
instead.

Traits: A Mechanism for Fine-grained Reuse
==========================================

A Trait is a unit of reuse much like a class, but only intended to group
functionality in a fine-grained and consistent way. It is not possible to
instantiate a Trait on its own. It is an addition to traditional inheritance
and enables horizontal composition of behavior.

The following code illustrates the current implementation of an extended
version of the PHP reflection API which provides detailed access to doc
comment
blocks.

ReflectionMethod and ReflectionFunction are classes from the reflection API
and
have to be extended with exactly the same code. In some situations it
would be possible to add a common base class, but in this case it is
impossible, because the extended classes are not under our control, i.e.,
they
are implemented in third party code or even in C, like it is the case here.
::

 <?php
 class ezcReflectionMethod extends ReflectionMethod {
   /* ... */
   function getReturnType() { /*1*/ }
   function getReturnDescription() { /*2*/ }
   /* ... */
 }

 class ezcReflectionFunction extends ReflectionFunction {
   /* ... */
   function getReturnType() { /*1*/ }
   function getReturnDescription() { /*2*/ }
   /* ... */
 }
 ?>

With Traits it is possible to refactor this redundant code out.
::

 <?php
 trait ezcReflectionReturnInfo {
   function getReturnType() { /*1*/ }
   function getReturnDescription() { /*2*/ }
 }

 class ezcReflectionMethod extends ReflectionMethod {
   use ezcReflectionReturnInfo;
   /* ... */
 }

 class ezcReflectionFunction extends ReflectionFunction {
   use ezcReflectionReturnInfo;
   /* ... */
 }
 ?> 

This is just a small example of what Traits are useful for.
The next sections will discuss on more advanced techniques and describe how
the
current implementation of Traits for PHP works.

The Flattening Property
-----------------------

As already mentioned, multiple inheritance and Mixins are complex
mechanisms.
Traits are an alternative which have been designed to impose no
additional semantics on classes. Traits are only entities of the literal
code
written in your source files. There is no notion about Traits at runtime.
They are used to group methods and reuse code and are totally flattened 
into the classes composed from them. It is almost like a language supported
and
failsafe copy'n'paste mechanism to build classes.

Precedence Order
""""""""""""""""

Flattening is achieved by applying some simple rules on the composition
mechanism. Instead of implementing a fancy and awkward algorithm to solve
problems, the entire control about the composition is left in the hand of
the
developer and fits nicely into the known inheritance model of PHP.
The following examples illustrate the semantics of Traits and their relation
to methods defined in classes.
::

 <?php
 class Base {
   public function sayHello() {
     echo 'Hello ';
   }
 }
 
 trait SayWorld {
   public function sayHello() {
     parent::sayHello();
     echo 'World!';
   }
 }

 class MyHelloWorld extends Base {
   use SayWorld;
 }

 $o = new MyHelloWorld();
 $o->sayHello(); // echos Hello World!
 ?>

As shown in the above code, an inherited method from a base class is
overridden
by the method inserted into ``MyHelloWorld`` from the ``SayWorld`` Trait.
The behavior is the same for methods defined in the ``MyHelloWorld`` class.
The precedence order is that methods from the current class override Trait
methods,
which in return override methods from the base class.
::

 <?php
 trait HelloWorld {
   public function sayHello() {
     echo 'Hello World!';
   }
 }

 class TheWorldIsNotEnough {
   use HelloWorld;
   public function sayHello() {
     echo 'Hello Universe!';
   }
 }

 $o = new TheWorldIsNotEnough();
 $o->sayHello(); // echos Hello Universe!
 ?>

Multiple Traits Usage
"""""""""""""""""""""

To keep things simple in the beginning, there has only one Trait being used
at
a time, but obviously a class could use multiple Traits at the same time.
::

 <?php
 trait Hello {
   public function sayHello() {
     echo 'Hello ';
   }
 }

 trait World {
   public function sayWorld() {
     echo ' World';
   }
 }
 
 class MyHelloWorld {
   use Hello;
   use World;
   public function sayExclamationMark() {
     echo '!';
   }
 }
 
 $o = new MyHelloWorld();
 $o->sayHello();
 $o->sayWorld();
 $o->sayExclamationMark();
 // Results eventually in: Hello World!

Conflict Resolution
"""""""""""""""""""

But now a problem will occur, if different Traits provide methods with the
same name.
::

 <?php
 trait A {
   public function smallTalk() {
     echo 'a';
   }
   public function bigTalk() {
     echo 'A';
   }
 }

 trait B {
   public function smallTalk() {
     echo 'b';
   }
   public function bigTalk() {
     echo 'B';
   }
 }
 ?>

Both classes have to be used in a class named ``Talker``. Multiple
inheritance
and Mixins define an algorithm to resolve this conflict. Traits don't.
Conflicts
aren't solved implicitly by any kind of precedence. Instead, to avoid
implicit
complexity, the developer has full control over class composition.
::

 <?php
 class Talker {
   use A;
   use B;
 }
 ?>
 
In case of the above definition of ``Talker``, PHP will show a notice that
there
have been conflicts and name the methods ``smallTalk()`` and ``bigTalk()`` 
as the reason of this conflict. Therefore, neither of the given
implementations
will be available in the class.

Instead, the developer can exactly define which methods are used and how the
conflict is resolved.
::

 <?php
 class Talker {
   use A { !smallTalk }
   use B { !bigTalk }
 }
 ?>

This definition will result in the exclusion of ``smallTalk()`` from the
Trait A
and ``bigTalk()`` from Trait B. Therefore, the resulting class Talker would 
echo ``'b'`` for ``smallTalk()`` and ``'A'`` for ``bigTalk().``
But simple exclusion of methods is not the best choice for all situations.
::

 <?php
 class Talker {
   use A { !smallTalk }
   use B { !bigTalk, talk => bigTalk }
 }
 ?>
 
Beside the exclusion an alias operation is available, too. This alias
operation, notated like a ``key => value`` for arrays even has a similar 
semantics like the array notation. The definition ``talk => bigTalk`` 
lets the new name ``talk`` refer to the method body of ``bigTalk``
of the Trait B. The resulting ``Talker`` class will consist of following
three methods:

* ``bigTalk() { echo 'A'; }``
* ``smallTalk() { echo 'b'; }``
* ``talk() { echo 'B'; }``

Since the alias operation adds a new name to an existing method body, the
``bigTalk`` method still has to be excluded. Otherwise, PHP would print
a notice that two methods from Traits have a conflict and are excluded.
Aliasing is not renaming and references in methods to a given method name
aren't changed either. On the first look this may sound strange, but it
provides the opportunity to build Traits and even hierarchies of Traits
which
fit together very well.

Traits Composed from Traits
"""""""""""""""""""""""""""

Not explicitly mentioned jet, but implied by the flattening property is the
composition of Traits from Traits.
Since Traits are fully flattened away at compile time it is possible to use
Traits to compose Traits without any additional impact on the semantics.
The following code illustrates this::

 <?php
 trait Hello {
   public function sayHello() {
     echo 'Hello ';
   }
 }

 trait World {
   public function sayWorld() {
     echo 'World!';
   }
 }

 trait HelloWorld {
   use Hello;
   use World;
 }

 class MyHelloWorld {
   use HelloWorld;
 }

 $o = new MyHelloWorld();
 $o->sayHello();
 $o->sayWorld();
 // Results eventually in: Hello World!
 ?>

Traits itself can take part in arbitrary compositions, but Traits are not
part
of the inheritance tree i.e., it is not possible to inherit from a Trait to
avoid confusion and misuse of Traits.

Traits Semantics Summarized
---------------------------

1. Traits do not add runtime semantics, they only take part in the process
of
   building a class.
2. Traits integrate into the precedence order of method overriding.
3. To avoid complexity, conflicts between Trait methods have to be solved
   explicitly. Otherwise a notice is generated and the conflicting methods
   are excluded.
4. Specific methods can be excluded from a composition to handle conflicts.
5. Aliases can be defined for methods to enable reuse of conflicting
methods.
6. Traits can be composed from Traits.

As a result of this semantics, at runtime, classes build using Traits are
not distinguishable 
from classes not using Traits but traditional code duplication instead.
Semantics of ``parent`` and ``$this`` hasn't changed, too. Used in a Trait
method, they behave exactly the same as if the method has been defined in
the
class directly.

Visibility and Interfaces
-------------------------

Visibility modifiers have not been discussed so far. Since Traits are meant
as
units of reuse, modifiers should be changeable easily in the context of a
composed class. Therefore, the aliasing operation is able to change the
visibility modifier of a method, too.
::

 <?php
 trait HelloWorld {
   public function sayHello() {
     echo 'Hello World!';
   }
 }

 class MyClass1 {
   use HelloWorld { protected sayHello }
 }

 class MyClass2 {
   use HelloWorld { private doHelloWorld => sayHello }
 }
 ?>

The abstract and final modifiers are supported, too. Abstract methods in
Traits are commonly used to define requirements a Trait needs to have
implemented by a class. The static modifier is not supported, because it
would
change the methods semantics and references to ``$this`` would break.

Another important feature of PHP is the support of interfaces. A often used
metaphor to describe Traits is *Traits are interfaces with implementation*.
Traits can be utilized to provide the implementation for a specific
interface
and since an interface is a guarantee that some methods are available it
fits
in the concept of Traits which provides those methods very well.

To underpin this relationship, it is possible to declare that a Trait
implements an interface like this::

 <?php
 interface IHello {
   public function sayHello();
 }
 
 trait SayHello implements IHello {
   public function sayHello() {
     echo 'Hello World!';
   }
 }

 class MyHelloWorld {
   use SayHello;
 }
 
 $o = new MyHelloWorld();
 var_dump($o instanceof IHello);  // bool(true)

If a Trait implements an interface, this definition is propagated to the
class
using the Trait. Therefore, it is possible to provide implementations for an
interface
and reuse them in different classes.

Proposal and Patch
==================

This Request for Comments proposes a new language feature for PHP named
Traits.
Traits are a nice approach to enhance the capabilities to design conceptual
consistent class hierarchies and avoid code duplication.

The patch against the PHP_5_2 branch is available at
http://toolslave.net/snapshots/traits/traits.patch
The written test cases are located here:
http://toolslave.net/snapshots/traits/traits-tests.zip
Additionally, the SVN repo used for developing this patch is located at
https://instantsvc.svn.sourceforge.net/svnroot/instantsvc/branches/php-exten
sion/traits-php/ 

Alternative Syntax Proposals
----------------------------

This section collects proposals for alternative Traits syntaxes.

Traits Use Definition in the Class Header
"""""""""""""""""""""""""""""""""""""""""

Instead of declaring the Trait composition in the class body, it could be
defined in the class prologue like this::
 
 <?php
 trait Hello {
   public function sayHello() {}
 }


 class MyHelloWorld extends BaseClass
   uses Hello (hello => sayHello, !sayHello) 
 {
   public function foo() {}
 }
 ?>

The drawback of this notation is the implied notation of Traits as some kind
of
a type changing construct. Since they do not influence the type as their
major
feature, this notion would be misleading. Furthermore, this notation seams
to
have readability problems. Complex compositions are not as clearly arranged
as
they are with the *In-Body* notation.
A patch implementing this notation is available at:
http://toolslave.net/snapshots/traits/traits-head-syntax.patch


More about Traits
-----------------

As already mentioned, Traits is not a totally new concept, but the semantics
used in this proposal has been fully defined at first in 2003. For
scientific
information and papers about Traits
http://www.iam.unibe.ch/~scg/Research/Traits/
is a good starting point. Since it isn't a purely academic concepts, there
are
already languages supporting Traits out there. Squeak, Perl6, Scala, Slate,
Fortress and even for C#/Rotor implementation are available.

A detailed technical report has been published at 
http://www.iam.unibe.ch/~scg/Archive/Papers/Duca06bTOPLASTraits.pdf
It explains Traits and gives some formal proves about the soundness of
Traits, too.

Last but not least, in this Phd thesis
http://www.iam.unibe.ch/~scg/Archive/PhD/schaerli-phd.pdf
two case studies have been publish illustrating the benefits Traits are
providing.

---

## #35564 — dz@bitxtender.com — 2008-02-18T22:37:06+00:00

URL: https://externals.io/message/35562#35564 · In reply to: #35562

Fantastic. Nice RFC, nice explanation, nice design - I love it.

Can I

+1

already? :)


David




Am 18.02.2008 um 20:27 schrieb <php@stefan-marr.de> <php@stefan- 
marr.de>:

> Hi,
>
> during last six months I've studied a language construct called  
> Traits.
> It is a construct to allow fine-grained code reuse and in my opinon
> this would be a nice feature for PHP, which I did like to propose  
> here.
> The following RFC deals with the questions what Traits are, how they  
> are
> used, why they are usefull and how they do look like in PHP.
> A patch implementing this new language construct is available, too.
>
> Thank you for your attention and I'm looking forward to hear your  
> comments
> :)
>
> Kind Regards
> Stefan
>
>
>
> Request for Comments: Traits for PHP
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>
> :HTML: http://www.stefan-marr.de/artikel/rfc-traits-for-php.html
>
> ... contents::
>
> This RFC will discuss at first the motivation for Traits describing  
> the
> rationals
> and presenting a short real world use case. The main part will  
> describe the
> concept of Traits in detail using the syntax for Traits implemented  
> in a
> patch
> which is part of this proposal. In the end, the URL of the patch and
> additional resources about Traits are given.
>
> Introduction
> ============
>
> *Traits* is a mechanism for code reuse in single inheritance  
> languages such
> as PHP. A Trait is intended to reduce some limitations of single  
> inheritance
> by enabeling a developer to reuse sets of methods freely in several
> independent
> classes living in different class hierarchies.
> The semantics of the combination of Traits and classes is defined in  
> a way,
> which reduces complexity and avoids the typical problems associated  
> with
> multiple
> inheritance and Mixins.
>
> They are recognized for their potential in supporting better  
> composition
> and reuse, hence their integration in newer versions of languages
> such as Perl 6, Squeak, Scala, Slate and Fortress.
> Traits have also been ported to Java and C#.
>
>
> Why do we need Traits?
> ----------------------
>
> Code reuse is one of the main goals that object-oriented languages  
> try to
> achieve
> with inheritance. Unfortunately, single inheritance often forces the
> developer
> to take a decision in favor for either code reuse *or* conceptual  
> clean
> class
> hierarchies. To achieve code reuse, methods have either to be  
> duplicated or
> to be moved near the root of the class hierarchy, but this hampers
> understandability and maintainability of code.
>
> To circumvent this problems multiple inheritance and Mixins have been
> invented.
> But both of them are complex and hard to understand. PHP5
> has been explicitly designed with the clean and successful model of  
> Java in
> mind: single inheritance, but multiple interfaces. This decision has  
> been
> taken
> to avoid the known problems of for example C++.
> Traits have been invented to avoid those problems, too. They enable  
> designer
> to build
> conceptually clean class hierarchies without the need to consider  
> code reuse
> or
> complexity problems, but focusing on the real problem domain and
> maintainability
> instead.
>
> Traits: A Mechanism for Fine-grained Reuse
> ==========================================
>
> A Trait is a unit of reuse much like a class, but only intended to  
> group
> functionality in a fine-grained and consistent way. It is not  
> possible to
> instantiate a Trait on its own. It is an addition to traditional  
> inheritance
> and enables horizontal composition of behavior.
>
> The following code illustrates the current implementation of an  
> extended
> version of the PHP reflection API which provides detailed access to  
> doc
> comment
> blocks.
>
> ReflectionMethod and ReflectionFunction are classes from the  
> reflection API
> and
> have to be extended with exactly the same code. In some situations it
> would be possible to add a common base class, but in this case it is
> impossible, because the extended classes are not under our control,  
> i.e.,
> they
> are implemented in third party code or even in C, like it is the  
> case here.
> ::
>
> <?php
> class ezcReflectionMethod extends ReflectionMethod {
>   /* ... */
>   function getReturnType() { /*1*/ }
>   function getReturnDescription() { /*2*/ }
>   /* ... */
> }
>
> class ezcReflectionFunction extends ReflectionFunction {
>   /* ... */
>   function getReturnType() { /*1*/ }
>   function getReturnDescription() { /*2*/ }
>   /* ... */
> }
> ?>
>
> With Traits it is possible to refactor this redundant code out.
> ::
>
> <?php
> trait ezcReflectionReturnInfo {
>   function getReturnType() { /*1*/ }
>   function getReturnDescription() { /*2*/ }
> }
>
> class ezcReflectionMethod extends ReflectionMethod {
>   use ezcReflectionReturnInfo;
>   /* ... */
> }
>
> class ezcReflectionFunction extends ReflectionFunction {
>   use ezcReflectionReturnInfo;
>   /* ... */
> }
> ?>
>
> This is just a small example of what Traits are useful for.
> The next sections will discuss on more advanced techniques and  
> describe how
> the
> current implementation of Traits for PHP works.
>
> The Flattening Property
> -----------------------
>
> As already mentioned, multiple inheritance and Mixins are complex
> mechanisms.
> Traits are an alternative which have been designed to impose no
> additional semantics on classes. Traits are only entities of the  
> literal
> code
> written in your source files. There is no notion about Traits at  
> runtime.
> They are used to group methods and reuse code and are totally  
> flattened
> into the classes composed from them. It is almost like a language  
> supported
> and
> failsafe copy'n'paste mechanism to build classes.
>
> Precedence Order
> """"""""""""""""
>
> Flattening is achieved by applying some simple rules on the  
> composition
> mechanism. Instead of implementing a fancy and awkward algorithm to  
> solve
> problems, the entire control about the composition is left in the  
> hand of
> the
> developer and fits nicely into the known inheritance model of PHP.
> The following examples illustrate the semantics of Traits and their  
> relation
> to methods defined in classes.
> ::
>
> <?php
> class Base {
>   public function sayHello() {
>     echo 'Hello ';
>   }
> }
>
> trait SayWorld {
>   public function sayHello() {
>     parent::sayHello();
>     echo 'World!';
>   }
> }
>
> class MyHelloWorld extends Base {
>   use SayWorld;
> }
>
> $o = new MyHelloWorld();
> $o->sayHello(); // echos Hello World!
> ?>
>
> As shown in the above code, an inherited method from a base class is
> overridden
> by the method inserted into ``MyHelloWorld`` from the ``SayWorld``  
> Trait.
> The behavior is the same for methods defined in the ``MyHelloWorld``  
> class.
> The precedence order is that methods from the current class override  
> Trait
> methods,
> which in return override methods from the base class.
> ::
>
> <?php
> trait HelloWorld {
>   public function sayHello() {
>     echo 'Hello World!';
>   }
> }
>
> class TheWorldIsNotEnough {
>   use HelloWorld;
>   public function sayHello() {
>     echo 'Hello Universe!';
>   }
> }
>
> $o = new TheWorldIsNotEnough();
> $o->sayHello(); // echos Hello Universe!
> ?>
>
> Multiple Traits Usage
> """""""""""""""""""""
>
> To keep things simple in the beginning, there has only one Trait  
> being used
> at
> a time, but obviously a class could use multiple Traits at the same  
> time.
> ::
>
> <?php
> trait Hello {
>   public function sayHello() {
>     echo 'Hello ';
>   }
> }
>
> trait World {
>   public function sayWorld() {
>     echo ' World';
>   }
> }
>
> class MyHelloWorld {
>   use Hello;
>   use World;
>   public function sayExclamationMark() {
>     echo '!';
>   }
> }
>
> $o = new MyHelloWorld();
> $o->sayHello();
> $o->sayWorld();
> $o->sayExclamationMark();
> // Results eventually in: Hello World!
>
> Conflict Resolution
> """""""""""""""""""
>
> But now a problem will occur, if different Traits provide methods  
> with the
> same name.
> ::
>
> <?php
> trait A {
>   public function smallTalk() {
>     echo 'a';
>   }
>   public function bigTalk() {
>     echo 'A';
>   }
> }
>
> trait B {
>   public function smallTalk() {
>     echo 'b';
>   }
>   public function bigTalk() {
>     echo 'B';
>   }
> }
> ?>
>
> Both classes have to be used in a class named ``Talker``. Multiple
> inheritance
> and Mixins define an algorithm to resolve this conflict. Traits don't.
> Conflicts
> aren't solved implicitly by any kind of precedence. Instead, to avoid
> implicit
> complexity, the developer has full control over class composition.
> ::
>
> <?php
> class Talker {
>   use A;
>   use B;
> }
> ?>
>
> In case of the above definition of ``Talker``, PHP will show a  
> notice that
> there
> have been conflicts and name the methods ``smallTalk()`` and  
> ``bigTalk()``
> as the reason of this conflict. Therefore, neither of the given
> implementations
> will be available in the class.
>
> Instead, the developer can exactly define which methods are used and  
> how the
> conflict is resolved.
> ::
>
> <?php
> class Talker {
>   use A { !smallTalk }
>   use B { !bigTalk }
> }
> ?>
>
> This definition will result in the exclusion of ``smallTalk()`` from  
> the
> Trait A
> and ``bigTalk()`` from Trait B. Therefore, the resulting class  
> Talker would
> echo ``'b'`` for ``smallTalk()`` and ``'A'`` for ``bigTalk().``
> But simple exclusion of methods is not the best choice for all  
> situations.
> ::
>
> <?php
> class Talker {
>   use A { !smallTalk }
>   use B { !bigTalk, talk => bigTalk }
> }
> ?>
>
> Beside the exclusion an alias operation is available, too. This alias
> operation, notated like a ``key => value`` for arrays even has a  
> similar
> semantics like the array notation. The definition ``talk => bigTalk``
> lets the new name ``talk`` refer to the method body of ``bigTalk``
> of the Trait B. The resulting ``Talker`` class will consist of  
> following
> three methods:
>
> * ``bigTalk() { echo 'A'; }``
> * ``smallTalk() { echo 'b'; }``
> * ``talk() { echo 'B'; }``
>
> Since the alias operation adds a new name to an existing method  
> body, the
> ``bigTalk`` method still has to be excluded. Otherwise, PHP would  
> print
> a notice that two methods from Traits have a conflict and are  
> excluded.
> Aliasing is not renaming and references in methods to a given method  
> name
> aren't changed either. On the first look this may sound strange, but  
> it
> provides the opportunity to build Traits and even hierarchies of  
> Traits
> which
> fit together very well.
>
> Traits Composed from Traits
> """""""""""""""""""""""""""
>
> Not explicitly mentioned jet, but implied by the flattening property  
> is the
> composition of Traits from Traits.
> Since Traits are fully flattened away at compile time it is possible  
> to use
> Traits to compose Traits without any additional impact on the  
> semantics.
> The following code illustrates this::
>
> <?php
> trait Hello {
>   public function sayHello() {
>     echo 'Hello ';
>   }
> }
>
> trait World {
>   public function sayWorld() {
>     echo 'World!';
>   }
> }
>
> trait HelloWorld {
>   use Hello;
>   use World;
> }
>
> class MyHelloWorld {
>   use HelloWorld;
> }
>
> $o = new MyHelloWorld();
> $o->sayHello();
> $o->sayWorld();
> // Results eventually in: Hello World!
> ?>
>
> Traits itself can take part in arbitrary compositions, but Traits  
> are not
> part
> of the inheritance tree i.e., it is not possible to inherit from a  
> Trait to
> avoid confusion and misuse of Traits.
>
> Traits Semantics Summarized
> ---------------------------
>
> 1. Traits do not add runtime semantics, they only take part in the  
> process
> of
>   building a class.
> 2. Traits integrate into the precedence order of method overriding.
> 3. To avoid complexity, conflicts between Trait methods have to be  
> solved
>   explicitly. Otherwise a notice is generated and the conflicting  
> methods
>   are excluded.
> 4. Specific methods can be excluded from a composition to handle  
> conflicts.
> 5. Aliases can be defined for methods to enable reuse of conflicting
> methods.
> 6. Traits can be composed from Traits.
>
> As a result of this semantics, at runtime, classes build using  
> Traits are
> not distinguishable
> from classes not using Traits but traditional code duplication  
> instead.
> Semantics of ``parent`` and ``$this`` hasn't changed, too. Used in a  
> Trait
> method, they behave exactly the same as if the method has been  
> defined in
> the
> class directly.
>
> Visibility and Interfaces
> -------------------------
>
> Visibility modifiers have not been discussed so far. Since Traits  
> are meant
> as
> units of reuse, modifiers should be changeable easily in the context  
> of a
> composed class. Therefore, the aliasing operation is able to change  
> the
> visibility modifier of a method, too.
> ::
>
> <?php
> trait HelloWorld {
>   public function sayHello() {
>     echo 'Hello World!';
>   }
> }
>
> class MyClass1 {
>   use HelloWorld { protected sayHello }
> }
>
> class MyClass2 {
>   use HelloWorld { private doHelloWorld => sayHello }
> }
> ?>
>
> The abstract and final modifiers are supported, too. Abstract  
> methods in
> Traits are commonly used to define requirements a Trait needs to have
> implemented by a class. The static modifier is not supported,  
> because it
> would
> change the methods semantics and references to ``$this`` would break.
>
> Another important feature of PHP is the support of interfaces. A  
> often used
> metaphor to describe Traits is *Traits are interfaces with  
> implementation*.
> Traits can be utilized to provide the implementation for a specific
> interface
> and since an interface is a guarantee that some methods are  
> available it
> fits
> in the concept of Traits which provides those methods very well.
>
> To underpin this relationship, it is possible to declare that a Trait
> implements an interface like this::
>
> <?php
> interface IHello {
>   public function sayHello();
> }
>
> trait SayHello implements IHello {
>   public function sayHello() {
>     echo 'Hello World!';
>   }
> }
>
> class MyHelloWorld {
>   use SayHello;
> }
>
> $o = new MyHelloWorld();
> var_dump($o instanceof IHello);  // bool(true)
>
> If a Trait implements an interface, this definition is propagated to  
> the
> class
> using the Trait. Therefore, it is possible to provide  
> implementations for an
> interface
> and reuse them in different classes.
>
> Proposal and Patch
> ==================
>
> This Request for Comments proposes a new language feature for PHP  
> named
> Traits.
> Traits are a nice approach to enhance the capabilities to design  
> conceptual
> consistent class hierarchies and avoid code duplication.
>
> The patch against the PHP_5_2 branch is available at
> http://toolslave.net/snapshots/traits/traits.patch
> The written test cases are located here:
> http://toolslave.net/snapshots/traits/traits-tests.zip
> Additionally, the SVN repo used for developing this patch is located  
> at
> https://instantsvc.svn.sourceforge.net/svnroot/instantsvc/branches/php-exten
> sion/traits-php/
>
> Alternative Syntax Proposals
> ----------------------------
>
> This section collects proposals for alternative Traits syntaxes.
>
> Traits Use Definition in the Class Header
> """""""""""""""""""""""""""""""""""""""""
>
> Instead of declaring the Trait composition in the class body, it  
> could be
> defined in the class prologue like this::
>
> <?php
> trait Hello {
>   public function sayHello() {}
> }
>
>
> class MyHelloWorld extends BaseClass
>   uses Hello (hello => sayHello, !sayHello)
> {
>   public function foo() {}
> }
> ?>
>
> The drawback of this notation is the implied notation of Traits as  
> some kind
> of
> a type changing construct. Since they do not influence the type as  
> their
> major
> feature, this notion would be misleading. Furthermore, this notation  
> seams
> to
> have readability problems. Complex compositions are not as clearly  
> arranged
> as
> they are with the *In-Body* notation.
> A patch implementing this notation is available at:
> http://toolslave.net/snapshots/traits/traits-head-syntax.patch
>
>
> More about Traits
> -----------------
>
> As already mentioned, Traits is not a totally new concept, but the  
> semantics
> used in this proposal has been fully defined at first in 2003. For
> scientific
> information and papers about Traits
> http://www.iam.unibe.ch/~scg/Research/Traits/
> is a good starting point. Since it isn't a purely academic concepts,  
> there
> are
> already languages supporting Traits out there. Squeak, Perl6, Scala,  
> Slate,
> Fortress and even for C#/Rotor implementation are available.
>
> A detailed technical report has been published at
> http://www.iam.unibe.ch/~scg/Archive/Papers/Duca06bTOPLASTraits.pdf
> It explains Traits and gives some formal proves about the soundness of
> Traits, too.
>
> Last but not least, in this Phd thesis
> http://www.iam.unibe.ch/~scg/Archive/PhD/schaerli-phd.pdf
> two case studies have been publish illustrating the benefits Traits  
> are
> providing.

---

## #35565 — Richard Lynch — 2008-02-18T22:37:12+00:00

URL: https://externals.io/message/35562#35565 · In reply to: #35562

>  <?php
>  trait ezcReflectionReturnInfo {
>    function getReturnType() { /*1*/ }
>    function getReturnDescription() { /*2*/ }
>  }
>
>  class ezcReflectionMethod extends ReflectionMethod {
>    use ezcReflectionReturnInfo;

So it's just like an include for a re-used body of 'class' code.

Hmmmm.

Why not just allow 'include' here instead?

:-)

Forgive me if I'm missing something subtle/complex here, but I wonder
if a Trait is really the "right answer"...

Yes, the ability to add/exclude specific functions from two Traits is
"gone" with a simple 'include'... But so is the complexity of yet
another language construct...

-- 
Some people have a "gift" link here.
Know what I want?
I want you to buy a CD from some indie artist.
http://cdbaby.com/from/lynch
Yeah, I get a buck. So?

---

## #35567 — David Coallier — 2008-02-18T23:08:26+00:00

URL: https://externals.io/message/35562#35567 · In reply to: #35565

> 
> > […]
>
> So it's just like an include for a re-used body of 'class' code.
>
> Hmmmm.
>
> Why not just allow 'include' here instead?

Oh come on..

>
> :-)
>
> Forgive me if I'm missing something subtle/complex here, but I wonder
> if a Trait is really the "right answer"...
>
> Yes, the ability to add/exclude specific functions from two Traits is
> "gone" with a simple 'include'... But so is the complexity of yet
> another language construct...

Please if you do not understand a concept, do not bash it or degrade it.

Read the proposal, read about traits, read the thesis, read the patch,
then if you still don't understand, give up, and if you do understand,
you can complain.

Thanks,

>
> --
> Some people have a "gift" link here.
> Know what I want?
> I want you to buy a CD from some indie artist.
> http://cdbaby.com/from/lynch
> Yeah, I get a buck. So?
>
>
> --
> 
> 
>
>



-- 
David Coallier,
Founder & Software Architect,
Agora Production (http://agoraproduction.com)
51.42.06.70.18

---

## #35568 — Chris Stockton — 2008-02-18T23:16:37+00:00

URL: https://externals.io/message/35562#35568 · In reply to: #35567

How was his comment bashing? He asked a valid question.

-Chris


> 
> > […]
>
> Oh come on..
>
> > […]
>
> Please if you do not understand a concept, do not bash it or degrade it.
>
> Read the proposal, read about traits, read the thesis, read the patch,
> then if you still don't understand, give up, and if you do understand,
> you can complain.
>
> Thanks,
>
> > […]
>
>
>
> --
> David Coallier,
> Founder & Software Architect,
> Agora Production (http://agoraproduction.com)
> 51.42.06.70.18

---

## #35570 — Pierre Joye — 2008-02-18T23:24:57+00:00

URL: https://externals.io/message/35562#35570 · In reply to: #35567

Hi David,



> Read the proposal, read about traits, read the thesis, read the patch,
> then if you still don't understand, give up, and if you do understand,
> you can complain.

If you don't understand, ask. If you still don't understand ask again.
That's more the concept of RFC and open discussions.

The goal of a RFC is to get comments (yes, the C in RFC means comments).

Let discuss this request only now and don't begin pointless bitching
session, that's counter productive.

Cheers,
-- 
Pierre
http://blog.thepimp.net | http://www.libgd.org

---

## #35571 — Stefan Marr — 2008-02-18T23:36:32+00:00

URL: https://externals.io/message/35562#35571 · In reply to: #35565

> So it's just like an include for a re-used body of 'class' code.
>
> Hmmmm.
>
> Why not just allow 'include' here instead?
Well, think this would be a Mixin mechanism like in Ruby.

> Forgive me if I'm missing something subtle/complex here, but I wonder
> if a Trait is really the "right answer"...
>
> Yes, the ability to add/exclude specific functions from two Traits is
> "gone" with a simple 'include'... But so is the complexity of yet
> another language construct...
The problem here is that we will need a way to handle conflicts i.e.
methods defined in more than one of the includes.
The mixin way is to apply one include at a time. So conflicts are
solved by overriding already defined methods. But this solution is not
perfect at all since there exist situations where you can not find an
order for the includes which provides you with the needed method
implementations. Additionally you will not notice when a method in an
included hierarchy will break your semantics by overriding other
methods unexpectedly.

The Traits way is to enable the developers to decide on such conflicts
and give them the power to re-use the methods exactly needed in this
special situation, instead of doing some "magic"/linearization to
solve conflicts.

Kind Regards
Stefan

---

## #35572 — Larry Garfield — 2008-02-19T01:36:17+00:00

URL: https://externals.io/message/35562#35572 · In reply to: #35565

> 
> > […]
>
> So it's just like an include for a re-used body of 'class' code.
>
> Hmmmm.
>
> Why not just allow 'include' here instead?
>
> :-)

Because include requires the code in question to live in another file, which I 
don't always want.  

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"; }
}
trait B {
  function foo() { echo "B"; }
}
class C {
  use A;
  use B;
}
$c = new C();
$c->foo(); // prints "B" since that came second.

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.)

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.

-- 
Larry Garfield			AIM: LOLG42
larry@garfieldtech.com		ICQ: 6817012

"If nature has made any one thing less susceptible than all others of 
exclusive property, it is the action of the thinking power called an idea, 
which an individual may exclusively possess as long as he keeps it to 
himself; but the moment it is divulged, it forces itself into the possession 
of every one, and the receiver cannot dispossess himself of it."  -- Thomas 
Jefferson

---

## #35573 — Rasmus Lerdorf — 2008-02-19T01:45:15+00:00

URL: https://externals.io/message/35562#35573 · In reply to: #35572

Larry Garfield wrote:
> 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.

The idea here is that we want to be able to cache opcodes, classes and
functions and optimize them out of the runtime context so the executor
can skip creating classes and functions on every single request.  A lot
of the traffic on this list over the past couple of months seems to
ignore this basic premise.  Features such as autoload and runtime object
manipulation incur a huge performance hit in the sense that they change
something that was free before and not only add the cost of the feature
itself, but it also means the object in question now can no longer be
cached and has to be created on every single request.

This doesn't mean we can't consider such features, but people need to
also consider the performance implications.

-Rasmus

---

## #35574 — Larry Garfield — 2008-02-19T02:25:44+00:00

URL: https://externals.io/message/35562#35574 · In reply to: #35573

> Larry Garfield wrote:
> > […]
>
> The idea here is that we want to be able to cache opcodes, classes and
> functions and optimize them out of the runtime context so the executor
> can skip creating classes and functions on every single request.  A lot
> of the traffic on this list over the past couple of months seems to
> ignore this basic premise.  Features such as autoload and runtime object
> manipulation incur a huge performance hit in the sense that they change
> something that was free before and not only add the cost of the feature
> itself, but it also means the object in question now can no longer be
> cached and has to be created on every single request.
>
> This doesn't mean we can't consider such features, but people need to
> also consider the performance implications.
>
> -Rasmus

Indeed, those are a concern.  That's why I thought the closure proposal from 
late December was so promising, because it appeared (to my non-C-coding eyes) 
to not have any runtime compilation, just indirect calling.  

It looks like Traits as described in the original post wouldn't have a runtime 
cost, but might (depending on the cost of building the code references) have 
a notable compile cost.  Runtime would cost more, but could they be done in a 
non-terrible way?  (I don't know; that's why I'm asking.)  Is the lookup 
table for what functions exist within a class/object easy/fast to manipulate 
or slow?

-- 
Larry Garfield			AIM: LOLG42
larry@garfieldtech.com		ICQ: 6817012

"If nature has made any one thing less susceptible than all others of 
exclusive property, it is the action of the thinking power called an idea, 
which an individual may exclusively possess as long as he keeps it to 
himself; but the moment it is divulged, it forces itself into the possession 
of every one, and the receiver cannot dispossess himself of it."  -- Thomas 
Jefferson

---

## #35578 — Sebastian Bergmann — 2008-02-19T06:35:25+00:00

URL: https://externals.io/message/35562#35578 · In reply to: #35562

php@stefan-marr.de schrieb:
> The following RFC deals with the questions what Traits are, how they are
> used, why they are usefull and how they do look like in PHP.

  Thank you, Stefan, for your thorough RFC.

> A patch implementing this new language construct is available, too.

  I tested an earlier version of the patch back in December when I read
  (and commented on) the RFC.

  I like the idea of Traits and your implementation for PHP and would just
  love to see this make its way into PHP.

-- 
Sebastian Bergmann                          http://sebastian-bergmann.de/
GnuPG Key: 0xB85B5D69 / 27A7 2B14 09E4 98CD 6277 0E5B 6867 C514 B85B 5D69

---

## #35579 — Sebastian Bergmann — 2008-02-19T06:35:36+00:00

URL: https://externals.io/message/35562#35579 · In reply to: #35573

Rasmus Lerdorf schrieb:
> The idea here is that we want to be able to cache opcodes, classes and
> functions and optimize them out of the runtime context so the executor
> can skip creating classes and functions on every single request.

  Thanks to their Flattening Property, there should be no notion of traits
  at runtime. So once the compiler has flattened a trait into a class it
  is just normal oparrays APC needs to deal with. At least as far as I can
  see.

-- 
Sebastian Bergmann                          http://sebastian-bergmann.de/
GnuPG Key: 0xB85B5D69 / 27A7 2B14 09E4 98CD 6277 0E5B 6867 C514 B85B 5D69

---

## #35580 — Rasmus Lerdorf — 2008-02-19T06:42:32+00:00

URL: https://externals.io/message/35562#35580 · In reply to: #35579

Sebastian Bergmann wrote:
> Rasmus Lerdorf schrieb:
> > […]
> 
>   Thanks to their Flattening Property, there should be no notion of traits
>   at runtime. So once the compiler has flattened a trait into a class it
>   is just normal oparrays APC needs to deal with. At least as far as I can
>   see.

This was in response to the suggestion that it should be extended to do
runtime conditional modification of the classes.

-Rasmus

---

## #35581 — Sebastian Bergmann — 2008-02-19T06:45:38+00:00

URL: https://externals.io/message/35562#35581 · In reply to: #35580

Rasmus Lerdorf schrieb:
> This was in response to the suggestion that it should be extended to do
> runtime conditional modification of the classes.

  Ah, sorry.

-- 
Sebastian Bergmann                          http://sebastian-bergmann.de/
GnuPG Key: 0xB85B5D69 / 27A7 2B14 09E4 98CD 6277 0E5B 6867 C514 B85B 5D69

---

## #35582 — Richard Quadling — 2008-02-19T10:34:27+00:00

URL: https://externals.io/message/35562#35582 · In reply to: #35562

> Hi,
>
> during last six months I've studied a language construct called Traits.
> It is a construct to allow fine-grained code reuse and in my opinon
> this would be a nice feature for PHP, which I did like to propose here.
> The following RFC deals with the questions what Traits are, how they are
> used, why they are usefull and how they do look like in PHP.
> A patch implementing this new language construct is available, too.
>
> Thank you for your attention and I'm looking forward to hear your comments
> :)
>
> Kind Regards
> Stefan
>
>
>
> Request for Comments: Traits for PHP
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>
> :HTML: http://www.stefan-marr.de/artikel/rfc-traits-for-php.html
>
> ... contents::
>
> This RFC will discuss at first the motivation for Traits describing the
> rationals
> and presenting a short real world use case. The main part will describe the
> concept of Traits in detail using the syntax for Traits implemented in a
> patch
> which is part of this proposal. In the end, the URL of the patch and
> additional resources about Traits are given.
>
> Introduction
> ============
>
> *Traits* is a mechanism for code reuse in single inheritance languages such
> as PHP. A Trait is intended to reduce some limitations of single inheritance
> by enabeling a developer to reuse sets of methods freely in several
> independent
> classes living in different class hierarchies.
> The semantics of the combination of Traits and classes is defined in a way,
> which reduces complexity and avoids the typical problems associated with
> multiple
> inheritance and Mixins.
>
> They are recognized for their potential in supporting better composition
> and reuse, hence their integration in newer versions of languages
> such as Perl 6, Squeak, Scala, Slate and Fortress.
> Traits have also been ported to Java and C#.
>
>
> Why do we need Traits?
> ----------------------
>
> Code reuse is one of the main goals that object-oriented languages try to
> achieve
> with inheritance. Unfortunately, single inheritance often forces the
> developer
> to take a decision in favor for either code reuse *or* conceptual clean
> class
> hierarchies. To achieve code reuse, methods have either to be duplicated or
> to be moved near the root of the class hierarchy, but this hampers
> understandability and maintainability of code.
>
> To circumvent this problems multiple inheritance and Mixins have been
> invented.
> But both of them are complex and hard to understand. PHP5
> has been explicitly designed with the clean and successful model of Java in
> mind: single inheritance, but multiple interfaces. This decision has been
> taken
> to avoid the known problems of for example C++.
> Traits have been invented to avoid those problems, too. They enable designer
> to build
> conceptually clean class hierarchies without the need to consider code reuse
> or
> complexity problems, but focusing on the real problem domain and
> maintainability
> instead.
>
> Traits: A Mechanism for Fine-grained Reuse
> ==========================================
>
> A Trait is a unit of reuse much like a class, but only intended to group
> functionality in a fine-grained and consistent way. It is not possible to
> instantiate a Trait on its own. It is an addition to traditional inheritance
> and enables horizontal composition of behavior.
>
> The following code illustrates the current implementation of an extended
> version of the PHP reflection API which provides detailed access to doc
> comment
> blocks.
>
> ReflectionMethod and ReflectionFunction are classes from the reflection API
> and
> have to be extended with exactly the same code. In some situations it
> would be possible to add a common base class, but in this case it is
> impossible, because the extended classes are not under our control, i.e.,
> they
> are implemented in third party code or even in C, like it is the case here.
> ::
>
>  <?php
>  class ezcReflectionMethod extends ReflectionMethod {
>    /* ... */
>    function getReturnType() { /*1*/ }
>    function getReturnDescription() { /*2*/ }
>    /* ... */
>  }
>
>  class ezcReflectionFunction extends ReflectionFunction {
>    /* ... */
>    function getReturnType() { /*1*/ }
>    function getReturnDescription() { /*2*/ }
>    /* ... */
>  }
>  ?>
>
> With Traits it is possible to refactor this redundant code out.
> ::
>
>  <?php
>  trait ezcReflectionReturnInfo {
>    function getReturnType() { /*1*/ }
>    function getReturnDescription() { /*2*/ }
>  }
>
>  class ezcReflectionMethod extends ReflectionMethod {
>    use ezcReflectionReturnInfo;
>    /* ... */
>  }
>
>  class ezcReflectionFunction extends ReflectionFunction {
>    use ezcReflectionReturnInfo;
>    /* ... */
>  }
>  ?>
>
> This is just a small example of what Traits are useful for.
> The next sections will discuss on more advanced techniques and describe how
> the
> current implementation of Traits for PHP works.
>
> The Flattening Property
> -----------------------
>
> As already mentioned, multiple inheritance and Mixins are complex
> mechanisms.
> Traits are an alternative which have been designed to impose no
> additional semantics on classes. Traits are only entities of the literal
> code
> written in your source files. There is no notion about Traits at runtime.
> They are used to group methods and reuse code and are totally flattened
> into the classes composed from them. It is almost like a language supported
> and
> failsafe copy'n'paste mechanism to build classes.
>
> Precedence Order
> """"""""""""""""
>
> Flattening is achieved by applying some simple rules on the composition
> mechanism. Instead of implementing a fancy and awkward algorithm to solve
> problems, the entire control about the composition is left in the hand of
> the
> developer and fits nicely into the known inheritance model of PHP.
> The following examples illustrate the semantics of Traits and their relation
> to methods defined in classes.
> ::
>
>  <?php
>  class Base {
>    public function sayHello() {
>      echo 'Hello ';
>    }
>  }
>
>  trait SayWorld {
>    public function sayHello() {
>      parent::sayHello();
>      echo 'World!';
>    }
>  }
>
>  class MyHelloWorld extends Base {
>    use SayWorld;
>  }
>
>  $o = new MyHelloWorld();
>  $o->sayHello(); // echos Hello World!
>  ?>
>
> As shown in the above code, an inherited method from a base class is
> overridden
> by the method inserted into ``MyHelloWorld`` from the ``SayWorld`` Trait.
> The behavior is the same for methods defined in the ``MyHelloWorld`` class.
> The precedence order is that methods from the current class override Trait
> methods,
> which in return override methods from the base class.
> ::
>
>  <?php
>  trait HelloWorld {
>    public function sayHello() {
>      echo 'Hello World!';
>    }
>  }
>
>  class TheWorldIsNotEnough {
>    use HelloWorld;
>    public function sayHello() {
>      echo 'Hello Universe!';
>    }
>  }
>
>  $o = new TheWorldIsNotEnough();
>  $o->sayHello(); // echos Hello Universe!
>  ?>
>
> Multiple Traits Usage
> """""""""""""""""""""
>
> To keep things simple in the beginning, there has only one Trait being used
> at
> a time, but obviously a class could use multiple Traits at the same time.
> ::
>
>  <?php
>  trait Hello {
>    public function sayHello() {
>      echo 'Hello ';
>    }
>  }
>
>  trait World {
>    public function sayWorld() {
>      echo ' World';
>    }
>  }
>
>  class MyHelloWorld {
>    use Hello;
>    use World;
>    public function sayExclamationMark() {
>      echo '!';
>    }
>  }
>
>  $o = new MyHelloWorld();
>  $o->sayHello();
>  $o->sayWorld();
>  $o->sayExclamationMark();
>  // Results eventually in: Hello World!
>
> Conflict Resolution
> """""""""""""""""""
>
> But now a problem will occur, if different Traits provide methods with the
> same name.
> ::
>
>  <?php
>  trait A {
>    public function smallTalk() {
>      echo 'a';
>    }
>    public function bigTalk() {
>      echo 'A';
>    }
>  }
>
>  trait B {
>    public function smallTalk() {
>      echo 'b';
>    }
>    public function bigTalk() {
>      echo 'B';
>    }
>  }
>  ?>
>
> Both classes have to be used in a class named ``Talker``. Multiple
> inheritance
> and Mixins define an algorithm to resolve this conflict. Traits don't.
> Conflicts
> aren't solved implicitly by any kind of precedence. Instead, to avoid
> implicit
> complexity, the developer has full control over class composition.
> ::
>
>  <?php
>  class Talker {
>    use A;
>    use B;
>  }
>  ?>
>
> In case of the above definition of ``Talker``, PHP will show a notice that
> there
> have been conflicts and name the methods ``smallTalk()`` and ``bigTalk()``
> as the reason of this conflict. Therefore, neither of the given
> implementations
> will be available in the class.
>
> Instead, the developer can exactly define which methods are used and how the
> conflict is resolved.
> ::
>
>  <?php
>  class Talker {
>    use A { !smallTalk }
>    use B { !bigTalk }
>  }
>  ?>
>
> This definition will result in the exclusion of ``smallTalk()`` from the
> Trait A
> and ``bigTalk()`` from Trait B. Therefore, the resulting class Talker would
> echo ``'b'`` for ``smallTalk()`` and ``'A'`` for ``bigTalk().``
> But simple exclusion of methods is not the best choice for all situations.
> ::
>
>  <?php
>  class Talker {
>    use A { !smallTalk }
>    use B { !bigTalk, talk => bigTalk }
>  }
>  ?>
>
> Beside the exclusion an alias operation is available, too. This alias
> operation, notated like a ``key => value`` for arrays even has a similar
> semantics like the array notation. The definition ``talk => bigTalk``
> lets the new name ``talk`` refer to the method body of ``bigTalk``
> of the Trait B. The resulting ``Talker`` class will consist of following
> three methods:
>
> * ``bigTalk() { echo 'A'; }``
> * ``smallTalk() { echo 'b'; }``
> * ``talk() { echo 'B'; }``
>
> Since the alias operation adds a new name to an existing method body, the
> ``bigTalk`` method still has to be excluded. Otherwise, PHP would print
> a notice that two methods from Traits have a conflict and are excluded.
> Aliasing is not renaming and references in methods to a given method name
> aren't changed either. On the first look this may sound strange, but it
> provides the opportunity to build Traits and even hierarchies of Traits
> which
> fit together very well.
>
> Traits Composed from Traits
> """""""""""""""""""""""""""
>
> Not explicitly mentioned jet, but implied by the flattening property is the
> composition of Traits from Traits.
> Since Traits are fully flattened away at compile time it is possible to use
> Traits to compose Traits without any additional impact on the semantics.
> The following code illustrates this::
>
>  <?php
>  trait Hello {
>    public function sayHello() {
>      echo 'Hello ';
>    }
>  }
>
>  trait World {
>    public function sayWorld() {
>      echo 'World!';
>    }
>  }
>
>  trait HelloWorld {
>    use Hello;
>    use World;
>  }
>
>  class MyHelloWorld {
>    use HelloWorld;
>  }
>
>  $o = new MyHelloWorld();
>  $o->sayHello();
>  $o->sayWorld();
>  // Results eventually in: Hello World!
>  ?>
>
> Traits itself can take part in arbitrary compositions, but Traits are not
> part
> of the inheritance tree i.e., it is not possible to inherit from a Trait to
> avoid confusion and misuse of Traits.
>
> Traits Semantics Summarized
> ---------------------------
>
> 1. Traits do not add runtime semantics, they only take part in the process
> of
>    building a class.
> 2. Traits integrate into the precedence order of method overriding.
> 3. To avoid complexity, conflicts between Trait methods have to be solved
>    explicitly. Otherwise a notice is generated and the conflicting methods
>    are excluded.
> 4. Specific methods can be excluded from a composition to handle conflicts.
> 5. Aliases can be defined for methods to enable reuse of conflicting
> methods.
> 6. Traits can be composed from Traits.
>
> As a result of this semantics, at runtime, classes build using Traits are
> not distinguishable
> from classes not using Traits but traditional code duplication instead.
> Semantics of ``parent`` and ``$this`` hasn't changed, too. Used in a Trait
> method, they behave exactly the same as if the method has been defined in
> the
> class directly.
>
> Visibility and Interfaces
> -------------------------
>
> Visibility modifiers have not been discussed so far. Since Traits are meant
> as
> units of reuse, modifiers should be changeable easily in the context of a
> composed class. Therefore, the aliasing operation is able to change the
> visibility modifier of a method, too.
> ::
>
>  <?php
>  trait HelloWorld {
>    public function sayHello() {
>      echo 'Hello World!';
>    }
>  }
>
>  class MyClass1 {
>    use HelloWorld { protected sayHello }
>  }
>
>  class MyClass2 {
>    use HelloWorld { private doHelloWorld => sayHello }
>  }
>  ?>
>
> The abstract and final modifiers are supported, too. Abstract methods in
> Traits are commonly used to define requirements a Trait needs to have
> implemented by a class. The static modifier is not supported, because it
> would
> change the methods semantics and references to ``$this`` would break.
>
> Another important feature of PHP is the support of interfaces. A often used
> metaphor to describe Traits is *Traits are interfaces with implementation*.
> Traits can be utilized to provide the implementation for a specific
> interface
> and since an interface is a guarantee that some methods are available it
> fits
> in the concept of Traits which provides those methods very well.
>
> To underpin this relationship, it is possible to declare that a Trait
> implements an interface like this::
>
>  <?php
>  interface IHello {
>    public function sayHello();
>  }
>
>  trait SayHello implements IHello {
>    public function sayHello() {
>      echo 'Hello World!';
>    }
>  }
>
>  class MyHelloWorld {
>    use SayHello;
>  }
>
>  $o = new MyHelloWorld();
>  var_dump($o instanceof IHello);  // bool(true)
>
> If a Trait implements an interface, this definition is propagated to the
> class
> using the Trait. Therefore, it is possible to provide implementations for an
> interface
> and reuse them in different classes.
>
> Proposal and Patch
> ==================
>
> This Request for Comments proposes a new language feature for PHP named
> Traits.
> Traits are a nice approach to enhance the capabilities to design conceptual
> consistent class hierarchies and avoid code duplication.
>
> The patch against the PHP_5_2 branch is available at
> http://toolslave.net/snapshots/traits/traits.patch
> The written test cases are located here:
> http://toolslave.net/snapshots/traits/traits-tests.zip
> Additionally, the SVN repo used for developing this patch is located at
> https://instantsvc.svn.sourceforge.net/svnroot/instantsvc/branches/php-exten
> sion/traits-php/
>
> Alternative Syntax Proposals
> ----------------------------
>
> This section collects proposals for alternative Traits syntaxes.
>
> Traits Use Definition in the Class Header
> """""""""""""""""""""""""""""""""""""""""
>
> Instead of declaring the Trait composition in the class body, it could be
> defined in the class prologue like this::
>
>  <?php
>  trait Hello {
>    public function sayHello() {}
>  }
>
>
>  class MyHelloWorld extends BaseClass
>    uses Hello (hello => sayHello, !sayHello)
>  {
>    public function foo() {}
>  }
>  ?>
>
> The drawback of this notation is the implied notation of Traits as some kind
> of
> a type changing construct. Since they do not influence the type as their
> major
> feature, this notion would be misleading. Furthermore, this notation seams
> to
> have readability problems. Complex compositions are not as clearly arranged
> as
> they are with the *In-Body* notation.
> A patch implementing this notation is available at:
> http://toolslave.net/snapshots/traits/traits-head-syntax.patch
>
>
> More about Traits
> -----------------
>
> As already mentioned, Traits is not a totally new concept, but the semantics
> used in this proposal has been fully defined at first in 2003. For
> scientific
> information and papers about Traits
> http://www.iam.unibe.ch/~scg/Research/Traits/
> is a good starting point. Since it isn't a purely academic concepts, there
> are
> already languages supporting Traits out there. Squeak, Perl6, Scala, Slate,
> Fortress and even for C#/Rotor implementation are available.
>
> A detailed technical report has been published at
> http://www.iam.unibe.ch/~scg/Archive/Papers/Duca06bTOPLASTraits.pdf
> It explains Traits and gives some formal proves about the soundness of
> Traits, too.
>
> Last but not least, in this Phd thesis
> http://www.iam.unibe.ch/~scg/Archive/PhD/schaerli-phd.pdf
> two case studies have been publish illustrating the benefits Traits are
> providing.

From a userland perspective (i.e. not knowing the internals impact),
this looks like a great feature which treats the userland developer
with a bit of respect.

It allows me to take a class and add some addition functionality to it
without subclassing.
Conflicts are MY responsibility to solve.
No magic.

From a userland developer, +1.

A question (and again, no idea on feasibility, internals, etc.).

The above proposal covers adding/overriding internal methods with
external ones. Is it possible to also include additional properties?

If not, then you would have to override the constructor method (this
could be demoted to documentation rather than code then I suppose).

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

---

## #35588 — Stefan Marr — 2008-02-19T12:00:03+00:00

URL: https://externals.io/message/35562#35588 · In reply to: #35572

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

---

## #35590 — troels knak-nielsen — 2008-02-19T12:19:49+00:00

URL: https://externals.io/message/35562#35590 · In reply to: #35562

> Hi,
>
> during last six months I've studied a language construct called Traits.
> It is a construct to allow fine-grained code reuse and in my opinon
> this would be a nice feature for PHP, which I did like to propose here.
> The following RFC deals with the questions what Traits are, how they are
> used, why they are usefull and how they do look like in PHP.
> A patch implementing this new language construct is available, too.
>
> Thank you for your attention and I'm looking forward to hear your comments
> :)
>
> Kind Regards
> Stefan

I know this is in the bike-shed department, but the following syntax
doesn't look very PHP to me:
  use B { !bigTalk, talk => bigTalk }

Could we separate exclusions from aliases somehow?

-- 
troels

---

## #35591 — Stefan Marr — 2008-02-19T12:23:57+00:00

URL: https://externals.io/message/35562#35591 · In reply to: #35582

Hi Richard,

> A question (and again, no idea on feasibility, internals, etc.).
>
> The above proposal covers adding/overriding internal methods with
> external ones. Is it possible to also include additional properties?
>
> If not, then you would have to override the constructor method (this
> could be demoted to documentation rather than code then I suppose).
the current proposal does not allow state in your traits.

At the moment the solution would be like this:

trait A {
   abstract protected function getFoo();
   public function doSomeFoo($bar) {
     return $this->getFoo().' baz ' . $bar;
   }
}

Traits can defined abstract methods to define a required method. This
abstract methods can be implemented in the class or in an other trait.

There are also notions about stateful traits out there. For instance
Scala does implement them, but state is an additional level of
complexity and I have tried to avoid it in this implementation, since
I have had expected much more complains about the aliasing and exclude
operations and its pretended complexity.
In my opinion stateful traits are the next logical step, but with the
cost for some additional complexity, since you need handle conflicting
properties. (The stateful traits approach is to make it private to a
traits composition, but this might not be obvious to every user.)

Kind Regards
Stefan

---

## #35592 — Christian Schneider — 2008-02-19T13:12:11+00:00

URL: https://externals.io/message/35562#35592 · In reply to: #35572

Larry Garfield wrote:
> 
> > […]
> Because include requires the code in question to live in another file, which I 
> don't always want.  

I'm with Richard Lynch here: Simply allow inclusion. No new language
concept, instead an existing one is made more orthogonal which is A
Desirable Thing(tm) IMHO.

About having it in the same file: You then need to also have the two
classes using the Trait to live in the same file (or include_once that
file) which is something I'm trying to avoid.

I've gotten fond of one class per file for the sake of an autoloader
anyway so I don't think separating the common code into a separate file
is a big disadvantage.

The part about being able to do partial Trait use seems hackish and
somewhat complicated to me so I'd rather not have it in the language. It
feels a little bit like being able to partially implement an Interface:
I think a class should either have a Trait or not. If we're using
include to emulate Traits then the same could be accomplished by
separating the parts into files (if *really* desired).

-1 for Traits as proposed
+1 for allowing include in class definitions

- Chris

---

## #35593 — Marcus Boerger — 2008-02-19T14:29:30+00:00

URL: https://externals.io/message/35562#35593 · In reply to: #35573

Hello Rasmus,

Tuesday, February 19, 2008, 2:45:15 AM, you wrote:

> Larry Garfield wrote:
> > […]

> The idea here is that we want to be able to cache opcodes, classes and
> functions and optimize them out of the runtime context so the executor
> can skip creating classes and functions on every single request.  A lot
> of the traffic on this list over the past couple of months seems to
> ignore this basic premise.  Features such as autoload and runtime object
> manipulation incur a huge performance hit in the sense that they change
> something that was free before and not only add the cost of the feature
> itself, but it also means the object in question now can no longer be
> cached and has to be created on every single request.

> This doesn't mean we can't consider such features, but people need to
> also consider the performance implications.

For that reason allowing traits in favor of include inside a class body is
much better.

Best regards,
 Marcus

---

## #35594 — Marcus Boerger — 2008-02-19T14:32:22+00:00

URL: https://externals.io/message/35562#35594 · In reply to: #35571

Hello Stefan,

  any dynamic aspect of a class has brought us to problems in inheritance
and required us to design the objct/compile model in a way that
inheritance often is done at run time. Imo traits are a way out of this.
In fact I'd love to issue a deprecated message as soon as class is found
outside of a main block.

marcus

Tuesday, February 19, 2008, 12:36:32 AM, you wrote:

> > […]
> Well, think this would be a Mixin mechanism like in Ruby.

> > […]
> The problem here is that we will need a way to handle conflicts i.e.
> methods defined in more than one of the includes.
> The mixin way is to apply one include at a time. So conflicts are
> solved by overriding already defined methods. But this solution is not
> perfect at all since there exist situations where you can not find an
> order for the includes which provides you with the needed method
> implementations. Additionally you will not notice when a method in an
> included hierarchy will break your semantics by overriding other
> methods unexpectedly.

> The Traits way is to enable the developers to decide on such conflicts
> and give them the power to re-use the methods exactly needed in this
> special situation, instead of doing some "magic"/linearization to
> solve conflicts.

> Kind Regards
> Stefan




Best regards,
 Marcus

---

## #35597 — Rasmus Lerdorf — 2008-02-19T15:59:19+00:00

URL: https://externals.io/message/35562#35597 · In reply to: #35594

Marcus Boerger wrote:
> Hello Stefan,
> 
>   any dynamic aspect of a class has brought us to problems in inheritance
> and required us to design the objct/compile model in a way that
> inheritance often is done at run time. Imo traits are a way out of this.
> In fact I'd love to issue a deprecated message as soon as class is found
> outside of a main block.

That would mean deprecating autoload as well since autoloading a class
is effectively the same as defining it outside of the main block.

-Rasmus

---

## #35598 — Marcus Boerger — 2008-02-19T16:58:29+00:00

URL: https://externals.io/message/35562#35598 · In reply to: #35597

Hello Rasmus,

  not really. We can have a table that keeps track of which class was
declared in what file. Then we could actually break down files into class
definitions and only import the requested part. In a perfect world each
class would be in its own file. A file would only create a single class and
nothing more or contain the code to generate output, probably some short,
flat procedural code. Then each of these files would get compiled and
cached. And loaded from those output generating files...

marcus

Tuesday, February 19, 2008, 4:59:19 PM, you wrote:

> Marcus Boerger wrote:
> > […]

> That would mean deprecating autoload as well since autoloading a class
> is effectively the same as defining it outside of the main block.

> -Rasmus




Best regards,
 Marcus

---

## #35599 — Marcus Boerger — 2008-02-19T16:58:37+00:00

URL: https://externals.io/message/35562#35599 · In reply to: #35562

Hello php,

  looks good to me. See more detailed thoughts in separate mail resonses.
The biggest issue I see is finding a syntax everyone likes.

Personally I like everything but one tiny piece, that is you do '!method'
to ignore a method from a trait. Since renaming happens in a php array like
style I would prefer to have that approach apply for ignoring methods as
well. The way to do that imo is 'method=>false' or 'method=>NULL' which both
should be obvious to PHP programmers that heard about Traits.

Other than that I'd even appriciate it, if we could get this for 5.3. I mean
come on guys it is ready and a very nice solution to the code reuse problem.

marcus

Monday, February 18, 2008, 8:27:00 PM, you wrote:

> Hi,

> during last six months I've studied a language construct called Traits.
> It is a construct to allow fine-grained code reuse and in my opinon
> this would be a nice feature for PHP, which I did like to propose here.
> The following RFC deals with the questions what Traits are, how they are
> used, why they are usefull and how they do look like in PHP.
> A patch implementing this new language construct is available, too.

> Thank you for your attention and I'm looking forward to hear your comments
> :)

> Kind Regards
> Stefan



> Request for Comments: Traits for PHP
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

> :HTML: http://www.stefan-marr.de/artikel/rfc-traits-for-php.html

> ... contents::

> This RFC will discuss at first the motivation for Traits describing the
> rationals
> and presenting a short real world use case. The main part will describe the
> concept of Traits in detail using the syntax for Traits implemented in a
> patch
> which is part of this proposal. In the end, the URL of the patch and 
> additional resources about Traits are given.

> Introduction
> ============

> *Traits* is a mechanism for code reuse in single inheritance languages such
> as PHP. A Trait is intended to reduce some limitations of single inheritance
> by enabeling a developer to reuse sets of methods freely in several
> independent
> classes living in different class hierarchies.
> The semantics of the combination of Traits and classes is defined in a way,
> which reduces complexity and avoids the typical problems associated with
> multiple
> inheritance and Mixins.

> They are recognized for their potential in supporting better composition
> and reuse, hence their integration in newer versions of languages 
> such as Perl 6, Squeak, Scala, Slate and Fortress.
> Traits have also been ported to Java and C#.


> Why do we need Traits?
> ----------------------

> Code reuse is one of the main goals that object-oriented languages try to
> achieve
> with inheritance. Unfortunately, single inheritance often forces the
> developer
> to take a decision in favor for either code reuse *or* conceptual clean
> class
> hierarchies. To achieve code reuse, methods have either to be duplicated or
> to be moved near the root of the class hierarchy, but this hampers
> understandability and maintainability of code.

> To circumvent this problems multiple inheritance and Mixins have been
> invented.
> But both of them are complex and hard to understand. PHP5
> has been explicitly designed with the clean and successful model of Java in
> mind: single inheritance, but multiple interfaces. This decision has been
> taken
> to avoid the known problems of for example C++.
> Traits have been invented to avoid those problems, too. They enable designer
> to build
> conceptually clean class hierarchies without the need to consider code reuse
> or
> complexity problems, but focusing on the real problem domain and
> maintainability
> instead.

> Traits: A Mechanism for Fine-grained Reuse
> ==========================================

> A Trait is a unit of reuse much like a class, but only intended to group
> functionality in a fine-grained and consistent way. It is not possible to
> instantiate a Trait on its own. It is an addition to traditional inheritance
> and enables horizontal composition of behavior.

> The following code illustrates the current implementation of an extended
> version of the PHP reflection API which provides detailed access to doc
> comment
> blocks.

> ReflectionMethod and ReflectionFunction are classes from the reflection API
> and
> have to be extended with exactly the same code. In some situations it
> would be possible to add a common base class, but in this case it is
> impossible, because the extended classes are not under our control, i.e.,
> they
> are implemented in third party code or even in C, like it is the case here.
> ::

>  <?php
>  class ezcReflectionMethod extends ReflectionMethod {
>    /* ... */
>    function getReturnType() { /*1*/ }
>    function getReturnDescription() { /*2*/ }
>    /* ... */
>  }

>  class ezcReflectionFunction extends ReflectionFunction {
>    /* ... */
>    function getReturnType() { /*1*/ }
>    function getReturnDescription() { /*2*/ }
>    /* ... */
>  }
>  ?>

> With Traits it is possible to refactor this redundant code out.
> ::

>  <?php
>  trait ezcReflectionReturnInfo {
>    function getReturnType() { /*1*/ }
>    function getReturnDescription() { /*2*/ }
>  }

>  class ezcReflectionMethod extends ReflectionMethod {
>    use ezcReflectionReturnInfo;
>    /* ... */
>  }

>  class ezcReflectionFunction extends ReflectionFunction {
>    use ezcReflectionReturnInfo;
>    /* ... */
>  }
>  ?> 

> This is just a small example of what Traits are useful for.
> The next sections will discuss on more advanced techniques and describe how
> the
> current implementation of Traits for PHP works.

> The Flattening Property
> -----------------------

> As already mentioned, multiple inheritance and Mixins are complex
> mechanisms.
> Traits are an alternative which have been designed to impose no
> additional semantics on classes. Traits are only entities of the literal
> code
> written in your source files. There is no notion about Traits at runtime.
> They are used to group methods and reuse code and are totally flattened 
> into the classes composed from them. It is almost like a language supported
> and
> failsafe copy'n'paste mechanism to build classes.

> Precedence Order
> """"""""""""""""

> Flattening is achieved by applying some simple rules on the composition
> mechanism. Instead of implementing a fancy and awkward algorithm to solve
> problems, the entire control about the composition is left in the hand of
> the
> developer and fits nicely into the known inheritance model of PHP.
> The following examples illustrate the semantics of Traits and their relation
> to methods defined in classes.
> ::

>  <?php
>  class Base {
>    public function sayHello() {
>      echo 'Hello ';
>    }
>  }
>  
>  trait SayWorld {
>    public function sayHello() {
>      parent::sayHello();
>      echo 'World!';
>    }
>  }

>  class MyHelloWorld extends Base {
>    use SayWorld;
>  }

>  $o = new MyHelloWorld();
>  $o->sayHello(); // echos Hello World!
>  ?>

> As shown in the above code, an inherited method from a base class is
> overridden
> by the method inserted into ``MyHelloWorld`` from the ``SayWorld`` Trait.
> The behavior is the same for methods defined in the ``MyHelloWorld`` class.
> The precedence order is that methods from the current class override Trait
> methods,
> which in return override methods from the base class.
> ::

>  <?php
>  trait HelloWorld {
>    public function sayHello() {
>      echo 'Hello World!';
>    }
>  }

>  class TheWorldIsNotEnough {
>    use HelloWorld;
>    public function sayHello() {
>      echo 'Hello Universe!';
>    }
>  }

>  $o = new TheWorldIsNotEnough();
>  $o->sayHello(); // echos Hello Universe!
>  ?>

> Multiple Traits Usage
> """""""""""""""""""""

> To keep things simple in the beginning, there has only one Trait being used
> at
> a time, but obviously a class could use multiple Traits at the same time.
> ::

>  <?php
>  trait Hello {
>    public function sayHello() {
>      echo 'Hello ';
>    }
>  }

>  trait World {
>    public function sayWorld() {
>      echo ' World';
>    }
>  }
>  
>  class MyHelloWorld {
>    use Hello;
>    use World;
>    public function sayExclamationMark() {
>      echo '!';
>    }
>  }
>  
>  $o = new MyHelloWorld();
>  $o->sayHello();
>  $o->sayWorld();
>  $o->sayExclamationMark();
>  // Results eventually in: Hello World!

> Conflict Resolution
> """""""""""""""""""

> But now a problem will occur, if different Traits provide methods with the
> same name.
> ::

>  <?php
>  trait A {
>    public function smallTalk() {
>      echo 'a';
>    }
>    public function bigTalk() {
>      echo 'A';
>    }
>  }

>  trait B {
>    public function smallTalk() {
>      echo 'b';
>    }
>    public function bigTalk() {
>      echo 'B';
>    }
>  }
>  ?>

> Both classes have to be used in a class named ``Talker``. Multiple
> inheritance
> and Mixins define an algorithm to resolve this conflict. Traits don't.
> Conflicts
> aren't solved implicitly by any kind of precedence. Instead, to avoid
> implicit
> complexity, the developer has full control over class composition.
> ::

>  <?php
>  class Talker {
>    use A;
>    use B;
>  }
>  ?>
>  
> In case of the above definition of ``Talker``, PHP will show a notice that
> there
> have been conflicts and name the methods ``smallTalk()`` and ``bigTalk()`` 
> as the reason of this conflict. Therefore, neither of the given
> implementations
> will be available in the class.

> Instead, the developer can exactly define which methods are used and how the
> conflict is resolved.
> ::

>  <?php
>  class Talker {
>    use A { !smallTalk }
>    use B { !bigTalk }
>  }
>  ?>

> This definition will result in the exclusion of ``smallTalk()`` from the
> Trait A
> and ``bigTalk()`` from Trait B. Therefore, the resulting class Talker would 
> echo ``'b'`` for ``smallTalk()`` and ``'A'`` for ``bigTalk().``
> But simple exclusion of methods is not the best choice for all situations.
> ::

>  <?php
>  class Talker {
>    use A { !smallTalk }
>    use B { !bigTalk, talk => bigTalk }
>  }
>  ?>
>  
> Beside the exclusion an alias operation is available, too. This alias
> operation, notated like a ``key => value`` for arrays even has a similar 
> semantics like the array notation. The definition ``talk => bigTalk`` 
> lets the new name ``talk`` refer to the method body of ``bigTalk``
> of the Trait B. The resulting ``Talker`` class will consist of following
> three methods:

> * ``bigTalk() { echo 'A'; }``
> * ``smallTalk() { echo 'b'; }``
> * ``talk() { echo 'B'; }``

> Since the alias operation adds a new name to an existing method body, the
> ``bigTalk`` method still has to be excluded. Otherwise, PHP would print
> a notice that two methods from Traits have a conflict and are excluded.
> Aliasing is not renaming and references in methods to a given method name
> aren't changed either. On the first look this may sound strange, but it
> provides the opportunity to build Traits and even hierarchies of Traits
> which
> fit together very well.

> Traits Composed from Traits
> """""""""""""""""""""""""""

> Not explicitly mentioned jet, but implied by the flattening property is the
> composition of Traits from Traits.
> Since Traits are fully flattened away at compile time it is possible to use
> Traits to compose Traits without any additional impact on the semantics.
> The following code illustrates this::

>  <?php
>  trait Hello {
>    public function sayHello() {
>      echo 'Hello ';
>    }
>  }

>  trait World {
>    public function sayWorld() {
>      echo 'World!';
>    }
>  }

>  trait HelloWorld {
>    use Hello;
>    use World;
>  }

>  class MyHelloWorld {
>    use HelloWorld;
>  }

>  $o = new MyHelloWorld();
>  $o->sayHello();
>  $o->sayWorld();
>  // Results eventually in: Hello World!
>  ?>

> Traits itself can take part in arbitrary compositions, but Traits are not
> part
> of the inheritance tree i.e., it is not possible to inherit from a Trait to
> avoid confusion and misuse of Traits.

> Traits Semantics Summarized
> ---------------------------

> 1. Traits do not add runtime semantics, they only take part in the process
> of
>    building a class.
> 2. Traits integrate into the precedence order of method overriding.
> 3. To avoid complexity, conflicts between Trait methods have to be solved
>    explicitly. Otherwise a notice is generated and the conflicting methods
>    are excluded.
> 4. Specific methods can be excluded from a composition to handle conflicts.
> 5. Aliases can be defined for methods to enable reuse of conflicting
> methods.
> 6. Traits can be composed from Traits.

> As a result of this semantics, at runtime, classes build using Traits are
> not distinguishable 
> from classes not using Traits but traditional code duplication instead.
> Semantics of ``parent`` and ``$this`` hasn't changed, too. Used in a Trait
> method, they behave exactly the same as if the method has been defined in
> the
> class directly.

> Visibility and Interfaces
> -------------------------

> Visibility modifiers have not been discussed so far. Since Traits are meant
> as
> units of reuse, modifiers should be changeable easily in the context of a
> composed class. Therefore, the aliasing operation is able to change the
> visibility modifier of a method, too.
> ::

>  <?php
>  trait HelloWorld {
>    public function sayHello() {
>      echo 'Hello World!';
>    }
>  }

>  class MyClass1 {
>    use HelloWorld { protected sayHello }
>  }

>  class MyClass2 {
>    use HelloWorld { private doHelloWorld => sayHello }
>  }
>  ?>

> The abstract and final modifiers are supported, too. Abstract methods in
> Traits are commonly used to define requirements a Trait needs to have
> implemented by a class. The static modifier is not supported, because it
> would
> change the methods semantics and references to ``$this`` would break.

> Another important feature of PHP is the support of interfaces. A often used
> metaphor to describe Traits is *Traits are interfaces with implementation*.
> Traits can be utilized to provide the implementation for a specific
> interface
> and since an interface is a guarantee that some methods are available it
> fits
> in the concept of Traits which provides those methods very well.

> To underpin this relationship, it is possible to declare that a Trait
> implements an interface like this::

>  <?php
>  interface IHello {
>    public function sayHello();
>  }
>  
>  trait SayHello implements IHello {
>    public function sayHello() {
>      echo 'Hello World!';
>    }
>  }

>  class MyHelloWorld {
>    use SayHello;
>  }
>  
>  $o = new MyHelloWorld();
>  var_dump($o instanceof IHello);  // bool(true)

> If a Trait implements an interface, this definition is propagated to the
> class
> using the Trait. Therefore, it is possible to provide implementations for an
> interface
> and reuse them in different classes.

> Proposal and Patch
> ==================

> This Request for Comments proposes a new language feature for PHP named
> Traits.
> Traits are a nice approach to enhance the capabilities to design conceptual
> consistent class hierarchies and avoid code duplication.

> The patch against the PHP_5_2 branch is available at
> http://toolslave.net/snapshots/traits/traits.patch
> The written test cases are located here:
> http://toolslave.net/snapshots/traits/traits-tests.zip
> Additionally, the SVN repo used for developing this patch is located at
> https://instantsvc.svn.sourceforge.net/svnroot/instantsvc/branches/php-exten
> sion/traits-php/ 

> Alternative Syntax Proposals
> ----------------------------

> This section collects proposals for alternative Traits syntaxes.

> Traits Use Definition in the Class Header
> """""""""""""""""""""""""""""""""""""""""

> Instead of declaring the Trait composition in the class body, it could be
> defined in the class prologue like this::
>  
>  <?php
>  trait Hello {
>    public function sayHello() {}
>  }


>  class MyHelloWorld extends BaseClass
>    uses Hello (hello => sayHello, !sayHello) 
>  {
>    public function foo() {}
>  }
>  ?>

> The drawback of this notation is the implied notation of Traits as some kind
> of
> a type changing construct. Since they do not influence the type as their
> major
> feature, this notion would be misleading. Furthermore, this notation seams
> to
> have readability problems. Complex compositions are not as clearly arranged
> as
> they are with the *In-Body* notation.
> A patch implementing this notation is available at:
> http://toolslave.net/snapshots/traits/traits-head-syntax.patch


> More about Traits
> -----------------

> As already mentioned, Traits is not a totally new concept, but the semantics
> used in this proposal has been fully defined at first in 2003. For
> scientific
> information and papers about Traits
> http://www.iam.unibe.ch/~scg/Research/Traits/
> is a good starting point. Since it isn't a purely academic concepts, there
> are
> already languages supporting Traits out there. Squeak, Perl6, Scala, Slate,
> Fortress and even for C#/Rotor implementation are available.

> A detailed technical report has been published at 
> http://www.iam.unibe.ch/~scg/Archive/Papers/Duca06bTOPLASTraits.pdf
> It explains Traits and gives some formal proves about the soundness of
> Traits, too.

> Last but not least, in this Phd thesis
> http://www.iam.unibe.ch/~scg/Archive/PhD/schaerli-phd.pdf
> two case studies have been publish illustrating the benefits Traits are
> providing.




Best regards,
 Marcus

---

## #35600 — Lukas Kahwe Smith — 2008-02-19T17:40:08+00:00

URL: https://externals.io/message/35562#35600 · In reply to: #35594

> In fact I'd love to issue a deprecated message as soon as class is  
> found
> outside of a main block.

err .. deprecated?
as in you want to deprecate the possibility entirely?
or you just want to hin to the user that its a bad idea .. (not sure  
if even `E_STRICT` would be a good fit there).

regards,
Lukas

---

Next page: https://externals.io/message/35562.md?page=2
