PHP traitについて調べてみる

多重継承出来ないPHPの苦肉の策っぽいものというイメージしかなかったtraitを今更だけど調べてみる。

結論、とても簡単に使えて便利。
しかし、自由すぎて怖い。
でも、extendsかuseかと割り切れば使う勇気が出る。

■シンプルな使い方

trait TraitTest{

    function message(){
        return 'Hello';
    }

}

class ClassTest{

    use TraitTest;      // 使用するTrait

}

$c = new ClassTest();
echo $c->message();     // Traitのメソッドがコールされ'Hello'が表示される

■trait内プライベート変数も使える

trait TraitTest{

    private $message;

    function setMessage($message){
        $this->message = $message;
    }

    function getMessage(){
        return $this->message;
    }

}

class ClassTest{

    use TraitTest;      // 使用するTrait

}

$c = new ClassTest();

$c->setMessage('Hello');
echo $c->getMessage();      // Hello

■複数のtraitをuseすることも出来る

trait Trait1{

    private $message;

    function setMessage($message){
        $this->message = $message;
    }

    function getMessage(){
        return $this->message;
    }

}

trait Trait2{

    private $val;

    function setVal($val){
        $this->val = $val;
    }

    function getVal(){
        return $this->val;
    }

}

class ClassTest{

    use Trait1, Trait2;

    public function message(){
        return 'class message';
    }

}

$c = new ClassTest();

$c->setMessage('abc');
echo $c->getMessage();          // abc

$c->setVal('xyz');
echo $c->getVal();              // xyz

■classとtraitに同じメソッドが存在する場合は、classが優先される

trait TraitTest{

    function message(){
        return 'trait1 message';
    }

}

class ClassTest{

    use TraitTest;

    public function message(){
        return 'class message';
    }

}

$c = new ClassTest();
echo $c->message();     // classのメソッドの'class message'が表示される

■複数のtraitに同じメソッドが存在する場合は、エラーとなる

trait Trait1{

    function getMessage(){
        return 'trait1 message';
    }

}

trait Trait2{

    function getMessage(){
        return 'trait2 message';
    }

}

class ClassTest{

    use Trait1, Trait2;

}

$c = new ClassTest();       // newした時点でエラーとなる
echo $c->getMessage();

■traitの中にtraitも可能

しかし、これをやるとソースが追えなくなりそう

trait Trait1{

    private $message;

    function setMessage($message){
        $this->message = $message;
    }

    function getMessage(){
        return $this->message;
    }

}

trait Trait2{

    private $val;

    function setVal($val){
        $this->val = $val;
    }

    function getVal(){
        return $this->val;
    }

}

trait Trait3{

    use Trait1, Trait2;

}

class ClassTest{

    use Trait3;

    public function message(){
        return 'class message';
    }

}

$c = new ClassTest();

$c->setMessage('abc');      // trait1のメソッドがコールされる
echo $c->getMessage();

$c->setVal('xyz');      // trait2のメソッドがコールされる
echo $c->getVal();

う~ん、上手に使えば恩恵を受けれそうだ。
しかし、まだtraitのデメリットをきちんと確認できてないので
大きなプロジェクトで使うのは怖いなぁ。

返信を残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です