PHP5.4のトレイト

PHP5.4にもtraitがあることを初めて知った。
のだけど、(当然だが)Scalaと全く同じようには使えないみたいで少し残念。

たとえば以下のようなScalaの実装。

object Sample {
  
  abstract class Say {
    def say: String
  }

  trait SayWorld extends Say {
    abstract override def say() = {
      super.say + " World"
    }
  }

  trait SaySpeakersName extends Say {
    def name: String
    abstract override def say() = {
      name + " said \"" + super.say + "\""
    }
  }

  class Hello(val name: String) extends Say {
    def say() = {
      "Hello"
    }
  }

  def main(args: Array[String]) = {
    val hello = new Hello("Alpha") with SayWorld with SaySpeakersName
    println(hello.say)
  }

}

結果:Alpha said "Hello World"

PHPでは一度別のクラスを経由する必要がある。

<?php
class BaseSay {
  public function say() {
    return "Hello";
  }
}

trait SayWorld {
  public function say() {
    return parent::say() . " world";
  }
}

trait SaySpeakersName {
  public function say() {
    return $this->name . ' said "' . parent::say() . '"';
  }
}

class BaseSayHello extends BaseSay {
  use SayWorld;
}

class Hello extends BaseSayHello {
  public $name;

  use SaySpeakersName;

  public function __construct($name)
  {
    $this->name = $name;
  }
}

$obj = new Hello("Beta");
echo $obj->say(), "\n";

結果:Beta said "Hello world"

うん、回りくどい。
しかしこれは、衝突を起こす方が利点があるという考え方でそうしてるんじゃないだろうか、とも思う。