Minule jsem zhruba nastínil základní myšlenku traitů, dnes se zmíním trochu více o dalších vlastnostech traitů vzhledem k dědičnosti, problémům při konfliktech jmen a kompozici. Všechny informace jsem čerpal z rfc na php wiki. Jak jsem tak koukal, je tam i další rfc, které se týká traitů a jejich použití vzhledem k rozsahu definice traitu a třídy, která trait použije, to jsem zatím nějak podrobněji nezkoumal.
Zarovnání vlastností
Vícenásobní dědičnost a mixiny jsou mnohem komplexnější mechanizmy než traity. trait sám o sobě nemá žádný dopad do runtime a chování tříd. Trait je vsunut a zarovnán do tříd, které ho používají, lze ho také přirovnat k bezpečnému kopírování kusu kódu do vytvářených tříd.
Zachování hierarchie
Traity zachovají dědičnost při kompozici v třídách s traity. Veškerá kontrola je ponechána na vývojáři.
class Base { public function sayHello() { echo 'Hello '; } } trait SayWorld { public function sayHello() { parent::sayHello(); echo 'World!'; } } class MyHelloWorld extends Base { use SayWorld; } $o = new MyHelloWorld(); $o->sayHello(); // echos Hello World!
Zděděná metoda Base třídy je přetížena ve třídě MyHelloWorld metodou vloženou traitem. Přetěžovat můžeme samozřejmě i v samotné třídě MyHelloWorld, toto přetížení má pak nejvyšší prioritu.
trait HelloWorld { public function sayHello() { echo 'Hello World!'; } } class TheWorldIsNotEnough { use HelloWorld; public function sayHello() { echo 'Hello Universe!'; } } $o = new TheWorldIsNotEnough(); $o->sayHello(); // echos Hello Universe!
Vícenásobné použití traitů a konflikty
Proč bychom nemohli použít více traitů? To by samozřejmě nevadilo, problém se pak může vyskytnout v případe, že traity obsahují stejné metody, pak dojde ke konfliktu.
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; }
Vícenásobní dědičnost a mixiny si s tím poradí, trait ne. Jen vývojář má plnou kontrolu nad kompozicí výsledné třídy. PHP by mělo formou informovat, že došlo ke konfliktu metod smallTalk()
a bigTalk()
a nadále pokračovat jakoby tam žádný trait nebyl.
Vývojář by měl mít možnost specifikovat, jak konflikt řešit.
class Talker { use A, B { B::smallTalk instead A::smallTalk, A::bigTalk instead B::bigTalk } }
Výše uvedené znamená vynechání smallTalk()
z traitu a bigTalk()
z traitu B. Protože samotné vyjmutí nemusí někdy stačit, bude možné i aliasovat použití traitu.
class Talker { use A, B { B::smallTalk instead A::smallTalk, A::bigTalk instead B::bigTalk, A::bigTalk as talk } }
Smysl je podobný jako u polí, výsledná třída Talker
pak bude obsahovat
- bigTalk() { echo 'A'; }
- smallTalk() { echo 'b'; }
- talk() { echo 'B'; }
Kompozice traitů
Protože traity jsou ve výsledku zarovnány do tříd, je možné traity skládat
trait Hello { public function sayHello() { echo 'Hello '; } } trait World { public function sayWorld() { echo 'World!'; } } trait HelloWorld { use Hello, World; } class MyHelloWorld { use HelloWorld; } $o = new MyHelloWorld(); $o->sayHello(); $o->sayWorld(); // Results eventually in: Hello World!
Abstraktní metody jako vyjádření nutnosti implementace v traitu
Pokud potřebujeme vyjádřit nutnost přítomnosti implementace nějaké funkce, která je potřeba v traitu, jako nejvhodnější se k tomu hodí abstraktní metody.
trait Hello { public function sayHelloWorld() { echo 'Hello'.$this->getWorld(); } abstract public function getWorld(); } class MyHelloWorld { private $world; use Hello; public function getWorld() { return $this->world; } public function setWorld($val) { $this->world = $val; } }
Tato možnost je preferovanější oproti dynamickému vyhodnocování příslušných metod za běhu zejména u komplexnějších projektů.
RFC na php wiki zmiňuje ještě další aspekty jako nastavení viditelnosti (public
, protected
) u metod v traitech a detaily k aliasingu. Také se tam nacházejí patche pro aktuální větvě PHP (5.2,5.3). Traity jsou rozhodně zajímavá věc, uvidíme, zda se traity v PHP někdy objeví, nicméně v dohledném horizontu s tím nelze moc počítat.
Komentáře (0)
Komentáře jsou uzavřeny.