Fórum Root.cz
Hlavní témata => Vývoj => Téma založeno: Jan Oktábec 10. 05. 2015, 15:20:06
-
Mám problém s následujícím kódem. Místo provedení příkazu:
echo "I need to do this operation :/...";
se zobrazí tato hláška:
Fatal error: Call to private method B::fun1() from context 'A' in C:\Server\www\classproblem.php on line 6
Ačkoli kód vypadá nesmyslně (volání funkce fun1 v constructu objektu A, ačkoli funkce fun1 je v objektu B, který je potomkem objektu A), je v případě mého projektu nutností. Proč to nejde? Mám místo $this v příkazu "$this->fun1();" použít něco jiného nebo funkce fun1 musí být public? :o
class A {
public function __construct ()
{
$this->fun1();
}
}
class B extends A {
private function fun1 ()
{
echo "I need to do this operation :/...";
}
}
$a = new B();
Mockát děkuji za odpovědi :) :D ;)
Jan Oktábec
-
Doplnění: Z důvodu bezpečnosti bych byl radši, aby zůstala private :/ Jinak když ji změním na public, tak to funguje...
-
co zkusit protected function fun1 () místo private function fun1 () ?
jenom tip, php nepoužívám
-
Ano, protected by to malo vyriesit. Protected znamena, ze bude private v materskej triede a aj v tej, ktora ju rozsiruje.
-
Vzhledem k tomu, že B není A, není v daném případě možné použít dědičnost.
-
Mám problém s následujícím kódem. Místo provedení příkazu:
echo "I need to do this operation :/...";
se zobrazí tato hláška:
Fatal error: Call to private method B::fun1() from context 'A' in C:\Server\www\classproblem.php on line 6
Ačkoli kód vypadá nesmyslně (volání funkce fun1 v constructu objektu A, ačkoli funkce fun1 je v objektu B, který je potomkem objektu A), je v případě mého projektu nutností. Proč to nejde? Mám místo $this v příkazu "$this->fun1();" použít něco jiného nebo funkce fun1 musí být public? :o
class A {
public function __construct ()
{
$this->fun1();
}
}
class B extends A {
private function fun1 ()
{
echo "I need to do this operation :/...";
}
}
$a = new B();
Mockát děkuji za odpovědi :) :D ;)
Jan Oktábec
abstract class A {
public function __construct ()
{
$this->fun1();
}
abstract protected function fun1();
}
class B extends A {
protected function fun1 ()
{
echo "I need to do this operation :/...";
}
}
$a = new B();
-
Prasím, prasíš, prasíme
-
Vzhledem k tomu, že B není A, není v daném případě možné použít dědičnost.
To je zas rada, jak noha. Člověk by čekal, že když se pořád odvoláváš na OOP, dědičnosti a návrhové vzory, tak to teď využiješ a dobře poradíš. A místo toho čteme zas jen fragment jak z automatického generátoru textů.
-
pan Oktabec,
vas kod *je* nezmyselny a popiera OOP. to ze je nutnostou vo vasom projekte a chcete prelomit oop, znamena len to, ze vas objektovy dizajn je zly.
ked mate triedu Netvor (vase A) a Trolla ktora dedi od Netvora (vase B), vy chcete
aby po vytvoreni vseobecneho Netvora sa zavolala metoda troll->sedPodMostom().
Netvor (vase A) je vseobecna trieda ktora nevidi a nepotrebuje a nechce vidiet do metod podtried pretoze by nebola znovupouzitelna
vy si myslite ze ked vyrobite Trolla a priradite ho do Netvora, zrazu trieda Netvor bude magicky vidiet do PRIVATNYCH metod Trolla (troll->dajSmrad()) ale takto to nefunguje
jedno z rieseni: vyrobit v Netvorovi protected metodu 'fun1', v Trollovi (a Drakovi a Hydre) ju prekryt.
alebo dajte konkretnejsi priklad namiesto A a B a fun1
To je zas rada, jak noha.
esteze tam nie su gettery a settery, to by sme si pochrochtali blahem
-
nez se clovek do cehokoliv pusti mel by mit aspon nezbytne teoreticke zaklady. je jedno jestli se jedna o kachlickovani koupelny, mdrání nebo OOP.
-
pan Oktabec,
vas kod *je* nezmyselny a popiera OOP. to ze je nutnostou vo vasom projekte a chcete prelomit oop, znamena len to, ze vas objektovy dizajn je zly.
ked mate triedu Netvor (vase A) a Trolla ktora dedi od Netvora (vase B), vy chcete
aby po vytvoreni vseobecneho Netvora sa zavolala metoda troll->sedPodMostom().
Netvor (vase A) je vseobecna trieda ktora nevidi a nepotrebuje a nechce vidiet do metod podtried pretoze by nebola znovupouzitelna
vy si myslite ze ked vyrobite Trolla a priradite ho do Netvora, zrazu trieda Netvor bude magicky vidiet do PRIVATNYCH metod Trolla (troll->dajSmrad()) ale takto to nefunguje
...
+1
Pěkně.
To je zas rada, jak noha.
esteze tam nie su g*y a s*y, to by sme si pochrochtali blahem
???
Ani naznačovat, ani naznačovat!!!
-
nez se clovek do cehokoliv pusti mel by mit aspon nezbytne teoreticke zaklady. je jedno jestli se jedna o kachlickovani koupelny, mdrání nebo OOP.
Modrání?
-
esteze tam nie su gettery a settery, to by sme si pochrochtali blahem
Jeste ze phpko neumi inline asm ... to bych videl na nejakej ten long jump, sak jit to prece musi.
----
A to si predstav, ze ti takovouhle prasecinu pak klidne prodaj.
-
Gettery a settery nie su problem. Problem je programator, ktory ich nevie spravne pouzivat alebo ich uz len z principu zavrhuje.
-
Nevím, co tu blbnete s trolama a netvorama. Uvedenej pattern je úplně normální, akorát by pro účely dokumentace a syntax checking mělo
bejt, že třída A je označena abstract a je v ní abstraktní metoda func1. To je celé na rovině "myšlenkové".
Na rovině faktické pak má PHP zmršenej koncept dědičnosti, takže tam nejde udělat abstraktní virtuální metoda private, takže to takto udělat nejde a musí holt ta metoda bejt protected. Pokud to chceš fakt mít private, tak není jiná cesta, než tu funkcionalitu vydělit do speciální třídy a dát ji jako private membera té třídy - ale já bych se s tím neštval :-)
-
Nevím, co tu blbnete s trolama a netvorama. Uvedenej pattern je úplně normální, akorát by pro účely dokumentace a syntax checking mělo
bejt, že třída A je označena abstract a je v ní abstraktní metoda func1. To je celé na rovině "myšlenkové".
Na rovině faktické pak má PHP zmršenej koncept dědičnosti, takže tam nejde udělat abstraktní virtuální metoda private, takže to takto udělat nejde a musí holt ta metoda bejt protected. Pokud to chceš fakt mít private, tak není jiná cesta, než tu funkcionalitu vydělit do speciální třídy a dát ji jako private membera té třídy - ale já bych se s tím neštval :-)
nielen v PHP sa neda vytovrit private abstact metoda. nejde to ani v jave a je to celkom logicke, private metoda sa ma pouzivat iba v triede kde je deklarovana. ostatne triedu ju nevidia, cize ju ani nemozu prepisat, aj ked je abstraktna.
-
Např. v C++ to jde a není na tom nic divného.
Říkáš tím: tady mám metodu, kterou zděděné třídy mají implementovat, ale nemají ji volat.
(PS: ponechávám vedle to, že princip privátních metod je kvůli testování poněkud problematický koncept jako takový).
-
samozrejme ale doraz je na tom 'abstract' ktory sa v zadani nenachadzal
s tym private abstract: nema ju ani c# ani java a predpokladam ze php kradlo oo dizajn z tohto sveta
-
Jo, php v poslední době dost Javovatí. A bohužel pravidla dědičnosti si taky bere od ní....
To ještě neznamená, že to jsou pravidla logická :-).
Zkuste si schválně níže tipnout, co bude výstupem tohodle programu (bez spouštění :-)).
public class Test {
public static void main(String[] args) {
Nested n = new Nested();
n.test();
n.print();
}
private void print() {
System.out.println("PRIVATE");
}
public static class Nested extends Test {
public void test() {
this.print();
super.print();
}
public void print() {
System.out.println("PUBLIC");
}
}
}
-
Jo, php v poslední době dost Javovatí. A bohužel pravidla dědičnosti si taky bere od ní....
To ještě neznamená, že to jsou pravidla logická :-).
Zkuste si schválně níže tipnout, co bude výstupem tohodle programu (bez spouštění :-)).
Privátní metody v Javě nejsou virtuální, když si to člověk uvědomí, tak pak to chování, na které poukazuje ten příklad, dává docela dobrý smysl.
-
tak pravidla javy su v mnohych pripadoch jednoduchsie ako c++: tie ohlasovane benefity v cpp ako vas private abstract su vyhodou len za komplexnejsie chapanie a viacero okrajovych a pripadov (a c++ teda nie je demonstracia jednoduchej syntaxe a semantiky jazyka potazmo v oop)
napr pravidlo v jave pre resolving metody je vdaka "vsetky metody su virtualne" velmi jednoduche: pozri na skutocny typ objektu a volaj nanom metodu. ak nenajdes pozri do rodica
btw odpoved je public private public
n ma typ Nested a
1) test() sa zavola na Nested
1a) this ktorym je objekt Nested teda print vracia PUBLIC (iny pripad nie je mozny, Nested je staticka trieda, cize this nemoze referovat na Test, aj keby chcela a toto nie je javascript)
1b) dalej sa zavola rodicovsky print, co je PRIVATE
2) n.print() zavola PUBLIC opat na Nested, preto PUBLIC
ten priklad je zial masturbacia nad moznostami syntaxe mimo realneho kodu hodna mozno tak java certifikatu... kde nechate kandidata na interview pat minut v hlave kompilovat kod a potom sa hrdit na fore tym ze vy ste to dali a on nie.
-
ok tak selfpwn nedal som to :D
super.print() je privatny to som si nevsimol, funguje to len vdaka tomu ze Nested.print vidi Test.print cez synteticky pristup ale to mi musel vysvetlit eclipse
-
Jo, php v poslední době dost Javovatí. A bohužel pravidla dědičnosti si taky bere od ní....
To ještě neznamená, že to jsou pravidla logická :-).
Zkuste si schválně níže tipnout, co bude výstupem tohodle programu (bez spouštění :-)).
public class Test {
public static void main(String[] args) {
Nested n = new Nested();
n.test();
n.print();
}
private void print() {
System.out.println("PRIVATE");
}
public static class Nested extends Test {
public void test() {
this.print();
super.print();
}
public void print() {
System.out.println("PUBLIC");
}
}
}
Nejak nechapu co by tady nemel clovek vedet. Mi na tom neprijde nic zvlastniho. Ale mozna jsem neco prehledl
-
napr pravidlo v jave pre resolving metody je vdaka "vsetky metody su virtualne" velmi jednoduche: pozri na skutocny typ objektu a volaj nanom metodu. ak nenajdes pozri do rodica
Pravidla v Javě jsou opravdu mnohem jednodušší než v C++, ale zase nejsou až tak jednoduchá, jak píšeš. Stručně: Napřed se prohledá třída i všichni její předci a vyberou se všechny metody, které jsou pro dané parametry aplikovatelné. Z nich se pak vybere ta, které je nejvíce specifická pro dané parametry.
Schválně si zkus něco takového:
class Param1 {}
class Param2 extends Param1 {}
class Class1 {
public void print(Param2 x) {
System.out.println("Class1.print(Param2 x)");
}
}
class Class2 extends Class1 {
public void print(Param1 x) {
System.out.println("Class2.print(Param1 x)");
}
}
public class Main {
public static void main(String[] args) {
(new Class2()).print(new Param2());
}
}
-
@Jakub Galgonek
jo, toto je dobra poznamka, dik
-
Jo, php v poslední době dost Javovatí. A bohužel pravidla dědičnosti si taky bere od ní....
To ještě neznamená, že to jsou pravidla logická :-).
Zkuste si schválně níže tipnout, co bude výstupem tohodle programu (bez spouštění :-)).
Co je na tom nelogického? Privátní metody jsou přístupné metodám a vnořeným třídám. Je to jinak než v C++, ale je to jen jiné řešení toho, co private vlastně znamená. Můžete si to přeložit tak, že vnořené třídy jsou automaticky friend.
Privátní metody v Javě nejsou virtuální, když si to člověk uvědomí, tak pak to chování, na které poukazuje ten příklad, dává docela dobrý smysl.
Privátní metody sice nejsou virtuální, ale volání super také není virtuální. Ostatní volání (přes this a n) by dala stejný výsledek, i kdyby ta metoda virtuální byla.
Pokud ten příklad chcete zajímavější, zkuste tohle:
class Test {
public static void main(String[] args) {
Nested n = new Nested();
n.test();
n.print();
Test t = n;
t.print();
}
private void print() {
System.out.println("PRIVATE");
}
public static class Nested extends Test {
public void test() {
this.print();
super.print();
}
public void print() {
System.out.println("PUBLIC");
}
}
}
-
Galonek:
Jasně, že když znáš pravidla, tak to víš. Jde o to, že logickej jazyk by měl mít pravidla "intuitivní".
A jak je vidět z reakce většiny diskutujících - evidentně intuitivní nejsou....
-
Jde o to, že logickej jazyk by měl mít pravidla "intuitivní".
Proto to by to logický jazyk měl dělat neintuitivně, tedy že programátor musí sdělit jak si to představuje. Třeba přepsání metody v potomku by nemělo jít přeložit bez toho, aby programátor nespecifikoval zda chce override nebo hide nebo overload. Bylo by to více psaní, ale odpadly by zbytečné nejasnosti.
-
ide tu o standardny rezim fungovania alebo ide o okrajovy pripad? v syntaxe tych mainstream jazykov je kopa pitfallov... otazka je ci je to naozaj pitfall alebo hra o ich hladani
(combo nested class dediaci od wrappujuceho classu je v jave code smell)
-
Je to případ dovedení ad absurdum, na kterém je vidět, že rozhodnutí, že to, že private metody budou nevirtuální je "zjednodušení pro kompilátor", které není intuitivní.
A které mj. vede k nemožnosti vyjádřit IMHO rozumnou myšlenku, abych zakázal volání funkce kterou musí definovat potomci, protože se vztahuje k nějaké specifické implementaci něčeho, ovšem jelikož ta funkce neudržuje objekt ve "well defined" stavu, tak by tu funkci potomci neměli mít možnost volat.
-
Je to případ dovedení ad absurdum, na kterém je vidět, že rozhodnutí, že to, že private metody budou nevirtuální je "zjednodušení pro kompilátor", které není intuitivní.
Tak ono tady nejde podle me tak o zjednoduseni pro kompilator, ale spise o vykon a moznou optimalizaci. Stejnej problem ma i napriklad jazyk D, ktery sice hodne vychazi z C++, ale zrovna OOP ma vice po vzoru javy.
-
Je to případ dovedení ad absurdum, na kterém je vidět, že rozhodnutí, že to, že private metody budou nevirtuální je "zjednodušení pro kompilátor", které není intuitivní.
Tak ono tady nejde podle me tak o zjednoduseni pro kompilator, ale spise o vykon a moznou optimalizaci. Stejnej problem ma i napriklad jazyk D, ktery sice hodne vychazi z C++, ale zrovna OOP ma vice po vzoru javy.
Výkonnostní optimalizace to asi nebude. Třeba takové final metody se volají pomocí invokevirtual, i když by je šlo přímo devirtualizovat. (Ony se tedy nakonec asi devirtualizují, ale jinde a bez ohledu na klíčové slovo final).
Podle mne jde spíše o zjednodušení pro člověka. On stav, kdy můžete překrýt (override) metodu, které je private v jiné třídě, ale nemůžete ji zavolat, přecejen trochu neintuitivní.
-
Co je neintuitivní se možná neshodem v globálu, ale pokud by možnost předefinování privátních metod byla např. omezená na metody označené jako abstract, tak co by bylo na tom neintuitivní?
Co je neintuitivního na tom, že je možné předefinovat metodu, která je přímo označená jako "todle musíš předefinovat"?
-
Co je neintuitivního na tom, že je možné předefinovat metodu, která je přímo označená jako "todle musíš předefinovat"?
Pokud je metoda označena "nesmíš o ní vědět" a "musíš ji předefinovat", tak je to prostě neintuitivní kombinace, a proto ji Java zakazuje.
-
Co je neintuitivní se možná neshodem v globálu, ale pokud by možnost předefinování privátních metod byla např. omezená na metody označené jako abstract, tak co by bylo na tom neintuitivní?
Co je neintuitivního na tom, že je možné předefinovat metodu, která je přímo označená jako "todle musíš předefinovat"?
Nemichas private s protected?
-
nez se clovek do cehokoliv pusti mel by mit aspon nezbytne teoreticke zaklady. je jedno jestli se jedna o kachlickovani koupelny, mdrání nebo OOP.
Škoda že nejde dať like :D
-
Na rovině faktické pak má PHP zmršenej koncept dědičnosti, takže tam nejde udělat abstraktní virtuální metoda private, takže to takto udělat nejde a musí holt ta metoda bejt protected.
On nejaký OOP jazyk umožnuje abstraktné súkromné metódy?
-
On nejaký OOP jazyk umožnuje abstraktné súkromné metódy?
Už to tu myslím padlo, v C++ to jde.
-
Jinak v Javě by se dal přístup k accessibility shrnout jako "co nemohu vidět, to pro mne neexistuje", což je trochu rozdíl oproti C++. Například následující příklad v C++ neprojde:
class A {};
class B : public A {};
class X {
public: void foo(A a){}
protected: void foo(B b){}
};
class Bar {
void bar(X x, B b) {
x.foo(b);
}
};
C++ zahlásí chybu, protože třída Bar nemá přístup k protected metodě X.foo(B). Javě to nevadí, ta prostě zavolá X.foo(A), kterou vidí a je na ten parametr aplikovatelná. Pozor jen, že pokud to budete v Javě zkoušet, tak je dobré mít X a Bar v jiných balíčcích, protože třídy z jednoho balíčku si navzájem vidí (a mohou tedy i volat) své protected metody.
-
A které mj. vede k nemožnosti vyjádřit IMHO rozumnou myšlenku, abych zakázal volání funkce kterou musí definovat potomci, protože se vztahuje k nějaké specifické implementaci něčeho, ovšem jelikož ta funkce neudržuje objekt ve "well defined" stavu, tak by tu funkci potomci neměli mít možnost volat.
occamova britva
rozumnych myslienok ktore nemaju podporu v jazyku je viac... napriklad plky voci chybajucej viacnasobnej dedicnosti v jave
zase vsak cim viac konstruktov tym je to vacsie psycho na ucenie sa a vysvetlovanie a chapanie... hec ved c++ vs java je otvoreny priklad (a v inej planete java vs scala)
-
napriklad plky voci chybajucej viacnasobnej dedicnosti v jave
Vícenásobná dědičnost chybí v mnoha jazycích a nikde k tomu nemají plnohodnotné uspokojivé řešení.
Konstrukty kterým programátor nerozumí, tak je nemusí používat.
-
aktivne nie ale stane sa ze ich bude citat a maintainovat po ostatnych :-))
-
rozumnych myslienok ktore nemaju podporu v jazyku je viac... napriklad plky voci chybajucej viacnasobnej dedicnosti v jave
Mě daleko víc vadí type erasure v generikách, takže třeba nelze udělat obecný wrapper přes dědičnost. Tohle u Javy trochu nedomysleli, generika jsou spíš pro dynamické jazyky.
-
....
aktivne nie ale stane sa ze ich bude citat a maintainovat po ostatnych :-))
Jo, to je přesně Javovskej protektivní přístup: někdo by to mohl používat blbě, tak to radši zakážeme.
Pokud je někdo čuník, tak je čuník, a seberestriktivnější jazyk mu nepomůže. A pokud někdo není čuník,
tak proč mu zakazovat užitečné obraty jen proto, že se s nimi dá prasit?
Jinak zakázání abstract private není konstrukce navíc, ale naopak restrikce navíc, stejně jako "devirtualizace"
private metod, z který to vychází, je opět pravidlo navíc a nikoli pravidlo namíň, takže ani ta argumentace
až tak nesedí....
-
aktivne nie ale stane sa ze ich bude citat a maintainovat po ostatnych :-))
Na údržbu starého kódu obvykle stačí pasivní znalosti. Když se nová featura ukáže jako přínosná, třeba lambda funkce, stejně se to bude muset naučit tak jako tak.
-
Jinak zakázání abstract private není konstrukce navíc, ale naopak restrikce navíc, stejně jako "devirtualizace"
private metod, z který to vychází, je opět pravidlo navíc a nikoli pravidlo namíň, takže ani ta argumentace
až tak nesedí....
Ono na to jde koukat také jinak: To, že jsou privátní metody nevirtuální, je spíše jen pouhý důsledek Java pravidel. Java rozdělení metod na virtuální a nevirtuální v podstatě nezná, takže klidně se na to můžeme koukat tak, že všechny metody jsou virtuální. Když se volá metoda, tak se najdou metody, které jsou accessibile, a z nich se nějaká vybere. Podobně při deklaraci metody - projdou se accessibile metody v předcích a pokud je tam nějaká se stejnou signaturou, provede se její overriding. Pokud se například v abstraktní třídě deklaruje metoda abstract void foo(), tak jediný, kdo ji bude moci implementovat, budou třídy ze stejného balíčku, protože jiné třídy prostě tuto metodu neuvidí. A přitom foo() virtuální jistě je.
-
napriklad plky voci chybajucej viacnasobnej dedicnosti v jave
Vícenásobná dědičnost chybí v mnoha jazycích a nikde k tomu nemají plnohodnotné uspokojivé řešení.
Konstrukty kterým programátor nerozumí, tak je nemusí používat.
Vícenásobná dědičnost v PHP nechybí. Rozumný vývojář se jí prostě vyhne.
-
Vícenásobná dědičnost v PHP nechybí. Rozumný vývojář se jí prostě vyhne.
Vyhne se jí jenom proto že musí, neboť autoři mnoha jazyků se ji neobtěžovali implementovat. Přirozená dědičnost je včetně vícenásobné.
-
Vícenásobná dědičnost v PHP nechybí. Rozumný vývojář se jí prostě vyhne.
Vyhne se jí jenom proto že musí, neboť autoři mnoha jazyků se ji neobtěžovali implementovat. Přirozená dědičnost je včetně vícenásobné.
Vícenásobná dědičnost je zbytečná, protože není přirozená. Dali ji jen do C++, ale evidentně to byla zásadní chyba.
Zkus uvést příklad použitelné násobné dědičnosti. Všechny případy, které jsem dosud viděl, byly jen uměle vykonstruované a neměly odraz v realitě.
-
Vícenásobná dědičnost v PHP nechybí. Rozumný vývojář se jí prostě vyhne.
Vyhne se jí jenom proto že musí, neboť autoři mnoha jazyků se ji neobtěžovali implementovat. Přirozená dědičnost je včetně vícenásobné.
Tak to neni zcela pravda, ja se ji vyhybam i v jazycich ktere ji podporuji, protoze pro me jeji vyuziti toho zas tolik neprinasi.
-
napriklad plky voci chybajucej viacnasobnej dedicnosti v jave
Vícenásobná dědičnost chybí v mnoha jazycích a nikde k tomu nemají plnohodnotné uspokojivé řešení.
Konstrukty kterým programátor nerozumí, tak je nemusí používat.
Vícenásobná dědičnost v PHP nechybí. Rozumný vývojář se jí prostě vyhne.
JJ jeji potreba je dosti sporna a pokud nekdy neco takoveho potrebujeme tak si ve vetsine pripadech clovek vystaci s kompozici. Napriklad jazyk D to resi elegantne:
module main;
import std.stdio;
struct Camera
{
void takePicture()
{
writeln("click");
}
}
class Phone
{
void call()
{
writeln("ring ring");
}
}
class CameraPhone : Phone
{
Camera camera;
alias camera this;
}
void main(string[] args)
{
auto phone = new CameraPhone();
phone.call();
phone.takePicture();
}
neceho podobneho jde v php taky dosahnout a to bud traitama:
<?php
trait TCamera
{
public function takePicture()
{
echo "click" . PHP_EOL;
}
}
trait TPhone
{
public function call()
{
echo "ring ring" . PHP_EOL;
}
}
class Camera
{
use TCamera;
}
class Phone
{
use TPhone;
}
class CameraPhone
{
use TCamera,TPhone;
}
$phone = new CameraPhone();
$phone->takePicture();
$phone->call();
nebo pres magicke metody __call, __callStatic,...
-
Vícenásobná dědičnost v PHP nechybí. Rozumný vývojář se jí prostě vyhne.
JJ jeji potreba je dosti sporna a pokud nekdy neco takoveho potrebujeme tak si ve vetsine pripadech clovek vystaci s kompozici. Napriklad jazyk D to resi elegantne:
... class CameraPhone : Phone ...
neceho podobneho jde v php taky dosahnout a to bud traitama...
nebo pres magicke metody __call, __callStatic,...
Tedy definovat CameraPhone jako telefon, který umí fotit. Šel by i fotoaparát, se kterým se dá telefonovat (také existují). Prostě nedefinovat Pegase jako křížence ptáka a koně, ale jako koně, který umí létat.
Traitům se vyhýbám kvůli snížení počtu WTF v kódu. Z podobných důvodů šetřím s metodami __call() a __callStatic(). Své použití však určitě mají - např. v adaptérech.