Cytat
Do tej pory można sobie było zdefiniować funkcję, ale nigdy nie było wiadomo czy w kolejnej wersji php nie wprowadzą funkcji o takiej samej nazwie i będzie problem.
Narzędziem do rozwiązywania tego problemu są przestrzenie nazw.
Cytat
Jako przykład traits widziałbym np. wrzucenie tam funkcji umożliwiających operacje na plikach/katalogach typu usuwanie katalogu z zawartością i potem wykorzystywanie w klasach które potrzebują takiej funkcjonalności.
Takie rzeczy jak odczytywanie katalogów czy usuwanie plików to dosyć skomplikowane operacje i powinny być one wykonywane przez zupełnie osobne obiekty.
Cytat
Część osób, nie bez powodów, widzi jego wykorzystanie w pewnych sytuacjach jako zastępnik Dependancy Injection Container.
Mógłbyś podać przykład takiej sytuacji, bo szczerze powiedziawszy ciężko mi jest sobie to wyobrazić.
Cytat
@wookieb: fajna właściwość... i co najważniejsze - logiczna. W końcu jeśli klasa używa konkretnego traitsa, to można się posłużyć wszystkim co on udostępnia, więc można to nazwać instancją traitsa, która jest bogatsza o to, czego traits jest "częścią".
Nie do końca logiczna, bo PHP umożliwia manipulowanie tym traitsem (można to słówko jakoś sensownie tłumaczyć). Innymi słowy metoda zdefiniowana jako publiczna w traitsie może zostać "przestawiona" na prywatną w danej klasie. Jednak nawet nie to jest tutaj powodem -
nigdy (nie potrafię znaleźć sytuacji poza jakimiś mechanizmami refleksji) nie powinno się interesować czy dany obiekt korzysta z traitsa czy nie - to jego wewnętrzna sprawa. W takich miejscach powinno użyć się interfejsów.
Co do samego pytania. Traitsy jakiejś wielkiej rewolucji nie wprowadzają - a przynajmniej nie powinny. Mało widzę dla nich sensownych zastosowań. Ale i w pewnych miejscach mogłyby być całkiem użyteczne. Gdzie? Na przykład przy domyślnej (albo jednej z predefiniowanej) implementacji interfejsu. Załóżmy, że mamy jakiś interfejs co do którego jesteśmy pewni, że większość jego implementacji będzie wyglądać dokładnie tak samo. Przykładowo interfejs
Symfony\Component\DependencyInjection\ContainerAwareInterface. Niemal w całym (a może i w całym) frameworku jak i w kodach aplikacji na nim zrealizowanych ten interfejs jest implementowany w następujący sposób:
class ... implements ContainerAwareInterface {
private $container;
function setContainer(ContainerInterface $container = null) {
$this->container = $container;
}
}
Nic by się nie stało gdyby istniał traits Symfony\Component\DependencyInjection\ContainerAwareInterfaceImplementation, wtedy w większości miejsc można by zastosować:
class ... implements ContainerAwareInterface {
use ContainerAwareInterfaceImplementation;
}
Oczywiście wszędzie sprawdzałoby się czy dany obiekt implementuje
interfejs ContainerAwareInterface, a nie traitsa ContainerAwareInterfaceImplementation.
Jednak nawet i tak nieinwazyjne zastosowanie ma wady - bo co jeśli ktoś zmieni definicję tego traitsa? Bardzo nieciekawy w diagnostyce problem.