Mam podklasę, która musi zwrócić podklasę typu zwracanego swojej klasy nadrzędnej. Wierzę, że jest to nazywane kowariantnym typem zwrotu. Zastanawiam się, najprostszy sposób na konwersję z rodzica na klasę podrzędną.Jaki jest właściwy sposób OO do konwersji obiektu na jedną z jego podklas (typ kowariantny)?
Odpowiedz
W PHP nie można "konwertować" obiektów z typu/klasy od A do B za pomocą funkcji dostępnej w języku.
Można to jednak zrobić, korzystając z serializacji, jeśli obiekty go obsługują (zwykle zwykłe stare obiekty PHP obsługują serializację). W formie porysowanej zmieniasz klasę obiektu i ponownie go zsyntezujesz. A zmienił się w B. Ale to nie jest płynne.
To powinno być komentarzem, ale zamierzam zrobić ważny punkt.
Programowanie to inżynieria i programowanie to projektowanie. Nie ma sposobu, aby powiedzieć, dlaczego projekt A jest lepszy niż projekt B, nie wiedząc, w jaki sposób będzie on używany. Zapytaj projektanta, czy przycisk przesyłania ma być czerwony czy zielony - a ona mówi: hmm, gdzie, na której stronie? Zapytaj inżyniera, czy powinieneś użyć belki lub sprzęgu - i odpowiedź będzie: zależy od tego, po co. Co sprawia, że możemy dać ci znaczącą poradę projektową, jeśli dasz nam tylko klasę "BrokenCar" metodą "foo". Powiedz nam, co właściwie chcemy osiągnąć z tym, w przeciwnym razie jedyną odpowiedzią mogę wymyślić jest
najlepszym sposobem korzystania z foo jest bar
Jak hakre stwierdził, rzucając do typów zdefiniowanych przez użytkownika nie jest natywnie możliwe w PHP (o ile wiem).
Co można zrobić, to stworzyć metodę w każdej klasie A lub B. coś takiego:
class A
{
public static function fromB(B $object)
{
/* your routine to convert an object of class B to an instance of class A */
}
/* or */
public static function fromA(A $object)
{
/* your routine to convert any object that is a subclass of A to a concrete instance of class A */
}
}
lub
class B
extends A
{
// this method could even be implemented in A already as well actually
public function toA()
{
/* your routine to convert this object to an object of class A */
}
}
W pierwszym przykładzie pierwszy factory method może być problematyczne, ponieważ wymaga od A posiadania konkretnej wiedzy na temat określonej podklasy. Musisz określić, czy jest to pożądane w twojej sytuacji. Być może mógłbyś to zoptymalizować, aby metoda fabryczna zaakceptowała obiekt, który dziedziczy po A, jak druga metoda fabryczna.
W drugim przykładzie B automatycznie już wie o A, ponieważ dziedziczy po nim. To może być bardziej pożądane. Ale pomyśl o tym, może to być nawet już zaimplementowane w A, tak, że metoda jest automatycznie dostępna we wszystkich podklasach A już.
Przepraszamy za niewyraźny przykład ... Starałem się uprościć to, co robiłem, być może zbyt wiele. Chciałem zilustrować, że "B" dostarcza dodatkowych metod, które nie istnieją w "A". "B" również nadpisuje niektóre metody z "A" w moim rzeczywistym kodzie. Mogłem skopiować logikę w nadpisanych metodach i po prostu przestałem nazywać rodzicielską metodę "foo", ale to było dużo duplikacji. –