Cecha to funkcjonalność, która została stworzona, z myślą o tych wszystkich programistach, którym bardzo brakuje możliwości oferowanych przez mechanizm wielokrotnego dziedziczenia. Może się bowiem zdarzyć sytuacja, w której implementowana klasa powinna dziedziczyć, nie po jednej, a po większej ilości klas. Dotychczas rozwiązanie to było niedostępne w PHP, jak i w większości nowoczesnych języków programowania. Cel takiego zagrania wydaje się być oczywisty. Zyskujemy zmniejszenie komplikacji tworzonych projektów, dzięki czemu zdecydowanie łatwiej prześledzić powiązania między klasami i zrozumieć całą strukturę aplikacji. Traits są więc panaceum na problemy związane z brakiem wielokrotnego dziedziczenia i będą one dostępne wraz z wydaniem PHP w wersji 5.4.
definicja
Trait to struktura, która formą deklaracji w dużym stopniu przypomina definicję klasy. Spójrzmy na poniższy przykład:
trait Write {
public function write () {
if (isset($this->myName))
echo $this->myName;
}
}
Słowo kluczowe trait służy do tworzenia cechy. Wewnątrz niej można umieszczać metody i atrybuty. Jak widać na powyższym skrypcie, istnieje tylko jedna funkcja z modyfikatorem dostępu – publicznym, która wysyła na wyjście wartość zmiennej $this->myName, o ile taką zdefiniowano w klasie, która z cechy korzysta. Sposób użycia ilustruje poniższy fragment kodu:
class Duck {
use Write;
private $myName;
public function __construct ($name) {
$this->myName = $name;
}
}
$obj = new Duck ('Donald');
echo $obj->write();
Aby klasa mogła w pełni rozkoszować się zaletami cechy Write korzystamy ze słówka kluczowego use.
przykład praktyczny
Aby lepiej zrozumieć i wyjaśnić sobie niuanse nowej funkcjonalności napiszmy parę cech, które będą implementować metody o takich samych nazwach:
trait Duck {
public function write ($message) {
echo 'Duck ',$message;
}
}
trait Monkey {
public function write ($message) {
echo 'Monkey ',$message;
}
}
trait Frog {
public function write ($message) {
echo 'Frog ',$message;
}
}
class Animal {
use Frog,Monkey,Duck;
}
$obj = new Animal();
Wykonanie powyższego skryptu skazane jest na porażkę, ponieważ niedozwolone jest korzystanie z wielu cech posiadających takie same nazwy metod. W taki wypadku programista jest zmuszony do wybrania konkretnej funkcji (słowo insteadof), a dla pozostałych skorzystanie z mechanizmu aliasów (słowo as):
//insteadof PRZYKLAD
class Animal {
use Frog,Monkey,Duck {Monkey::write insteadof Frog,Duck;}
}
$obj = new Animal();
$obj->write('test');
// mozemy uzyc tylko jednej z trzech metod
// as PRZYKLAD
class Animal {
use Frog,Monkey,Duck {
Monkey::write insteadof Duck,Frog;
Duck::write as writeDuck;
Frog::write as writeFrog;
}
}
$obj = new Animal();
$obj->writeFrog('test');
$obj->writeDuck('test');
$obj->write('test');
// mozemy skorzystac ze wszystkich trzech metod
Oczywiście nic nie stoi na przeszkodzie, by sama klasa Animal posiadała metodę write. W takiej sytuacji w pierwszej kolejności zostanie wywołana właśnie ona. Warto jeszcze wspomnieć o sposobności zmiany modyfikatora dostępu dla cechy. Prezentuje to poniższy przykład:
trait Duck {
private function write ($message) {
echo 'Duck ',$message;
}
}
trait Monkey {
private function write ($message) {
echo 'Monkey ',$message;
}
}
trait Frog {
private function write ($message) {
echo 'Frog ',$message;
}
}
class Animal {
use Frog,Monkey,Duck {
Monkey::write insteadof Duck,Frog;
Duck::write as public writeDuck;
Frog::write as public writeFrog;
Monkey::write as public;
}
}
$obj = new Animal();
$obj->write('test');
$obj->writeFrog('test');
$obj->writeDuck('test');
Wypada także zapamiętać, iż nie uda się nam utworzyć obiektu cechy lub skorzystać w jej przypadku z type hinting. Zainteresowanych zachęcam do własnych eksperymentów.
1 Odpowiedź : “traits”


PHP 5.4 wyszło, więc trzeba zacząć zabawę z nowinkami.