February 21, 2008

RFC: Traits for PHP

Reading PHP-internals list (http://news.php.net/php.internals) I found that Stefan Marr sent a very interesting patch.
It's an implementation of Traits for PHP.

But what does Traits stand for?


Traits are basically Behavioral Blocks which group functionality (they group methods / functions indeed).

Depending on which programming language we are keen on we are used to dealing with interfaces, making our object hierarchies implement these interfaces. For example:


Interface TheInterface
{
   public void method1();
   public int method2();
   ...
}

interface TheOtherInterface
{
   public void methodA();
   public int methodB();
   ...
}


class TheClass implements TheInterface, TheOtherInterface
{
   /* Here all methods corresponing to both interfaces
     * should be implemented
     */
}


But what happens with object hierarchies? Sometimes we have to choose between an elegant OO design, loyal to all the OOP concepts that we know (wtf?) like Encapsulation, Inheritance, Abstraction, Polymorphism (I really don't remember anything about these, I only know how to apply them..) that adequately represents the problem we want to model, OR, make a very nice and reusable code, not paying (too much) attention to best practices and principles of OOP...

So we have class hierarchies where classes extend other classes, creating complex families, with parent and child clases with inherit some of their parents' methods, with different access permissions (protected, private, final, sealed, etcetera, depending on the programming language...)

But sometimes, we have functionalities we would like all the class families to enjoy, for example: If we want all the families to know how to cook an asado, wherever they were born since they live in Argentina like me:

Let's consider this example:



We have a (not very useful) hierarchy, which models families of different origins. All the families have a surname and know how to procreate.
So families know how to cook different types of food, depending on their origin. The italian know how to cook pasta, risotto and canoli, japanese are expert sushi cookers and sake drinkers. We, the argentinean, know how to cook asado, drink mate and going to the cancha (soccer stadium), but not me... I don't go to the cancha.

It would be great if any family living in Argentina know how to cook asado and drink mate... So we can build a small "package", or Trait with different abilities, for example:

trait ArgentineanFood
{
   public void cookAsado(){
     // code to cook asado...
   }
   public void drinkMate(){
     // code to drink mate...
   }
}

So we could have a class like:

class ItalianFamily
{
   use ArgentineanFood;
   public void cookRisotto(){...}
   public void cookPasta(){...}
   public void cookCanoli(){...}
}

And easily have an italian family which knows how to cook and consume argentinean food, weird uh?? (I have to say that most of the Argentinean population has italian origins...)

I like to think that this is a way of crossing the hierarchy in an horizontal way, I try to explain this on the class diagram (click to enlarge):



Traits for PHP



There are lots of details to deal with. For example name conflicts. What happens if two traits have methods with the same name? who resolves this?

In this first implementation there is no conflict solving. In fact, traits are "flattened" inside the code of the class. The decision of which trait wins the conflict is left as a programmer decision.
We could do things like:

class Talker {
    use A { !smallTalk }
    use B { !bigTalk }
}

Where the Talker class has methods from traits A and B but exludes the method smallTalk from trait A and bigtalk from trait B. We can also rename trait methods while using it in a class.

One advantage we can find in this implementation is that it hasn't any runtime penalty, since its like a formal way to copy n' paste code.

I recommend you read what this guy Steffan wrote, everything for the PHP implementation is clearly explained.

Ok, so I quit writing not to bore you. I hope you could understand everything I wanted to share.

/g

Further reading
Read here.
more on traits here.
Or you can read Nathanael Schäarli's Thesis.

No comments: