Nowości z php.internals – newInstanceWithoutConstructor()

W dzisiejszym wpisie, Sebastian Bergmann, zaproponował dodanie do PHP metody ReflectionClass::newInstanceWithoutConstructor(), która to pozwoliła by na tworzenie nowej instancji klasy z pominięciem konstruktora, podobnie jak to odbywa się w przypadku deserializacji. Osobiście jestem bardzo entuzjastyczny wobec zgłoszonej propozycji i chętnie powitałbym ją w nadchodzącej wersji 5.4 interpretera.

Zastosowań jest całe multum, natomiast chyba najbardziej przydatna jest ta funkcja dla twórców wszelakiej maści frameworków i bibliotek (szczególnie ORM). Dzięki niej, nie trzeba już będzie korzystać ze sztuczek z serialize/deserialize, by stworzyć obiekt z pominięciem konstruktora.

  1. wookieb pisze:

    To raczej byłaby lipa. Po to jest konstruktor żeby wywoływał się automatycznie przy tworzeniu obiektu. Jak nie chcesz, żeby wykonywał się w ten sposób, nie tworzysz go. Jest masa inna opcji na takie zachowanie (metody init w konstruktorze, które można wyłączyć). Wyobrażasz sobie metody magiczne a następne mechanizmy do ich obchodzenia?

    Póki co jedynym sensownym zastosowaniem jakie widzę to np obchodzenie konstruktorów w klasach Final, które są po prostu źle napisane. Chyba, że znasz inne?

  2. Najbardziej oczywistym zastosowaniem jest, gdy np. chcemy odtworzyć jakiś obiekt z informacji w bazie danych w jakimś ORM-ie. Dzięki temu, użytkownik korzystający z ORM-a, może sobie napisać swoją klasę w dowolny sposób a my i tak będziemy potrafili ją odtworzyć z DB, najpierw tworząc obiekt z użyciem wspomnianej metody a później używając ReflectionProperty::setAccessible i ustawiając wartości dla pól prywatnych.

  3. lukanus pisze:

    A jak to jest teraz zaimplementowane w phpunit’cie i jego mock’ach ?
    Bo ma dokładnie taką metodę.

  4. wookieb pisze:

    Rozumiem. I właśnie tutaj występuje element, którego nie jestem w stanie zrozumieć. Dostęp do metod, właściwości prywatnych. Jestem zbyt ortodoksyjny w tej dziedzinie. Istnieją po to aby nikt niepowołany nie uzyskał do nich dostępu. Ale skoro tak wygląda sytuacja to nie ma wyboru… wprowadzać.

  5. wookieb pisze:

    Aktualnie PHPUnit robi trick z deserializacją. Aczkolwiek nadpisanie konstruktora i nie wywoływanie konstruktora również jest możliwe.

  6. wookieb pisze:

    „nie wywołanie konstruktora rodzica” *

  7. @wookieb: Ortodoksja jest wielce pożądana w pisaniu kodu, nazwijmy go „docelowym”. Natomiast w przypadku bibliotek, ważny jest cel, jak danej biblioteki się używa i czasami trzeba odpuścić podejściu ortodoksyjnemu aby biblioteka była super używalna – i tak nikt poza jej deweloperem nie powinien tykać wnętrzności a korzystać tylko z jej API.

  8. lukanus pisze:

    Z drugiej strony po za ‚tykaniem jej wnętrzności’, kiedy chcemy rozszerzyć funkcjonalności jakiejś biblioteki, prędzej czy później spotkamy się z chwilą kiedy żeby pobrać jedną wartość dla jakiegoś innego zastosowania niż zostało to zaprojektowane przez jej twórców, będziemy musieli po drodze zainicjalizować ’10 róznych obiektów’ tylko dlatego, że coś zostało zadeklarowane jako private member, albo w konstruktorze wymagane jest połączenie z ’10 bazami danych’.

  9. wookieb pisze:

    Faktycznie masz rację. Poluzuję chomąto :)

  10. @lukanus – dobrze napisany soft jest „closed for modification, open for extension” 😉

  11. Alan Gabriel Bem pisze:

    „To raczej byłaby lipa. Po to jest konstruktor żeby wywoływał się automatycznie przy tworzeniu obiektu.”

    @woobiekit, weź po uwagę, że to feature refleksji. A refleksje, co jak co, służą głównie do meta-programowania, co samo w sobie jest nieortodoksyjne.

  12. Zastanawia mnie co jest bardziej purystyczne – czy konstruktor wywołany po utworzeniu obiektu (inicjalizator) czy konstruktor jako funkcja tworząca obiekt ? :>

  13. lukanus pisze:

    Konstruktor jako funkcja tworząca obiekt z listą inicjalizacyjną ;P

  14. @lukanus – czyli fabryka ?

  15. lukanus pisze:

    @wojtek Nabijam się… nie ma czegoś takiego w php, jest za to w C++ :)

  16. Wiem, że jest w C++, natomiast najbardziej przypomina to fabrykę w spojrzeniu globalnym 😉

  1. There are no trackbacks for this post yet.

Leave a Reply

Informuj mnie o odpowiedziach poprzez e-mail. Możesz również subskrybować wpis bez zostawiania komentarza.