多重継承出来ない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のデメリットをきちんと確認できてないので
大きなプロジェクトで使うのは怖いなぁ。