How do I use traits in PHP 5.4

The biggest change in PHP 5.4 is the addition of traits to the object-oriented programmability. Traits prevent code duplication by allowing multiple classes to include a collection of methods implemented as a trait. This means multiple classes can include the same method implementations without duplicating code.

Traits improve on interfaces because they include not only the function definition, but also the implementation. Traits can also use other traits, meaning that one trait could be a collection of others. So, if you had traits Roll and Bounce, you could have trait Movements that used both Roll and Bounce.

trait HelloWorld {
    public function sayHello() {
        echo 'Hello ';
    }
 
    public function sayWorld() {
        echo 'World!';
    }
}
 
class MyClass {
    use HelloWorld;
    public function sayHelloWorld() {
        $this->sayhello();
        $this->sayWorld();
    }
}
 
$h = new MyClass();
$h->sayHelloWorld();      // outputs "Hello World!"

In implementing traits, the keywords trait and insteadof were added to PHP. Usage of trait is outlined above. The PHP keyword insteadof is used for conflict resolution. Here’s an example of how to use insteadof:

trait A {
    public function smallTalk() {
        echo 'a';
    }
    public function bigTalk() {
        echo 'A';
    }
}
 
trait B {
    public function smallTalk() {
        echo 'b';
    }
    public function bigTalk() {
        echo 'B';
    }
}
 
class Talker {
    use A, B {
        B::smallTalk insteadof A;
        A::bigTalk insteadof B;
    }
}
 
class Aliased_Talker {
    use A, B {
        B::smallTalk insteadof A;
        A::bigTalk insteadof B;
        B::bigTalk as talk;
    }
}

2 Comments so far »

  1. Rulatir said

    am March 7 2012 @ 10:28 am

    What’s the point of insteadof? Why isn’t it sufficient to just say “use B::smallTalk” etc.? Why are we forced to explicitly declare all the traits whose smallTalk methods we _won’t_ be using? It seems redundant, ugly, unorthogonal, and a maintenance nightmare. Consider this example:

    class HappyCodeReuse {

    use VendorA\CoolLibrary\someTrait,
    VendorB\HotLibrary\otherTrait,
    VendorC\LibWD\YATrait

    {
    VendorA\CoolLibrary\someTrait::foo
    insteadof VendorB\HotLibrary\otherTrait;
    }
    }

    Now imagine that Vendor C adds method foo() to their trait. This breaks our HappyCodeReuse class even though it already specifies that it wants method foo() from Vendor A’s class, period! In short: “insteadof” puts a burden on non-users. Absolutely unacceptable.

  2. Tim Barsness said

    am March 7 2012 @ 3:02 pm

    Wouldn’t using namespaces appropriately solve this conundrum?

    It makes sense to me to use insteadof because then you don’t have to explicitly add each method from a trait to a using class. This way if you added a method to a trait, you wouldn’t have to go to each class that uses that trait and give it “access” to the method.

Comment RSS

Leave a comment

Name: (Required)

eMail: (Required)

Website:

Comment: