Jestem więc całkiem nowy w programowaniu w świecie rzeczywistym (poza projektami akademickimi) i natrafiłem na wiele postów, które mówią, że używanie instanceof
jest złe, aby określić, jaką klasą jest dany obiekt.
Moja sytuacja jest taka, że mam trzy klasy, podstawową klasę produktu, jedną, która ją rozszerza, i drugą, która ją rozszerza. Wszystkie są przechowywane w tej samej tabeli w bazie danych i mam trochę kodu, który wymaga użycia metod na każdym z nich, aby pobrać dane.
Jaka jest najlepsza praktyka, aby obejść ten sposób? Przeczytałem kilka rzeczy o polimorfizmie, ale nie mogę znaleźć żadnych przykładów, które rozwiązałyby mój problem. Wszystkie zwykle zastępują metodę, która dla mnie nie działa, ponieważ muszę wyciągać różne rzeczy z różnych obiektów.
Czy istnieje lepszy sposób, aby to zrobić, czy utknąłem przy użyciu instanceof
lub jakiegoś odbicia, aby uzyskać pola specyficzne dla obiektów?
źródło
instanceof
jest nieprawidłowe; Problemem jest zazwyczaj próba znalezienia klasy obiektu. Nie zawsze źle, ale prawdopodobnie tak jest w twoim przypadku. Może jeśli powiesz nam, co próbujesz osiągnąć, możemy zaproponować rozwiązanie wykorzystujące polimorfizm.getSpecifics()
która jest implementowana w różny sposób dla każdej z nich, przy czym każda zwraca dane specyficzne dla klasy?Odpowiedzi:
Powód
instanceof
jest odradzany, ponieważ nie jest to OOP.Osoba wywołująca / użytkownik obiektu nie powinna mieć powodu, aby wiedzieć, która konkretna klasa jest instancją, poza którą typem zmiennej jest zadeklarowana.
Jeśli potrzebujesz różnych zachowań w podklasach, dodaj metodę i zaimplementuj je inaczej.
źródło
getSpecifics()
(lub coś podobnego) na każdej klasie, która zwróci specyfikę każdej klasy. Czy to najlepsze podejście?List
. Przekazuję go do obiektu, który bierze dowolnyIterable
. Teraz ten drugi obiekt przekazuje go do trzeciego obiektu, który zajmuje alboList
optymalizację, alboIterable
ale jest znacznie wolniejszy. Drugi nie powinien wiedzieć, że to lista, ale trzeci bardzo chciałby wiedzieć. Czy trzeci obiekt nie powinien sprawdzać, czy instancja może zastosować optymalizację? Zobacz na przykład guawaFluentIterable
, która właśnie to robi.instanceof
.instanceof
niekoniecznie jest złą rzeczą, jednak należy na to spojrzeć.Przykładem prawidłowego działania jest miejsce, w którym można uzyskać kolekcję typu podstawowego, a chcesz tylko te z podtypem. Odzyskiwanie adresów sieciowych z
NetworkInterface.getNetworkInterfaces()
powrotem zwraca obiekty NetworkInterface, które mają kolekcję obiektów InetAddress, niektóre z nich to Inet4Address, a niektóre Inet6Address. Jeśli chcemy filtrować kolekcję pod kątem obiektów Inet4Address, konieczne jest użycie instanceof.W sytuacji opisanej w oryginalnym poście istnieje klasa podstawowa, coś, co rozszerza tę klasę podstawową i coś, co rozszerza klasę rozszerzoną. Chociaż nie jest to w pełni pouczające, wydaje się, że ma to podstawy niektórych mniej niż idealnych projektów.
Gdy zwracasz klasę podstawową, chyba że istnieje uzasadniony powód, aby tak ją zaprojektować (zgodność wsteczna między specyfikacjami wcześniejszej wersji), nie powinieneś próbować zaglądać do typów bazowych. Jeśli otrzymasz zestaw, wiesz, że otrzymujesz zestaw. Pozwala to deweloperowi później zmienić zdanie, aby zwrócić bardziej konkretny typ (SortedSet) lub zmienić typ bazowy (HashSet na TreeSet) bez zerwania czegokolwiek.
Ponownie przeanalizuj projekt struktury obiektów i ich rodzicielstwa, aby zobaczyć, czy można stworzyć lepszy model klasy, który nie wymaga rozróżnienia typów.
źródło
isOfType(SomeEnum.IPv4)
metody może być lepszym sposobem na filtrowanie takich cech niż sprawdzanie konkretnego typu za pomocąinstanceof
. Co jeśli chcesz później podzielić klasę implementacji IPv4? Nie zawsze tak jest lepiej, ale to rozważanie.(o instanceof Serializable) || (o instanceof Externalizable)
. instanceof jest lepszy niż alternatywaMożesz użyć metody getClass ().
Czy na pewno potrzebujesz trzech różnych klas? Może jedna klasa z przełącznikiem w środku będzie służyć lepiej?
źródło
getClass
iinstanceof
dziel się wadami. Polimorfizm jest lepszy niż oba, gdy pasuje, i nie widzę, aby nie pasował do przypadku użycia OP.getClass
mam nadal nie dzielić ten sam problem, jak przy użyciuinstanceof
? Nadal będę musiał dowiedzieć się, który mam, a następnie wywołać zestaw funkcji. Idealnie chciałbym metody, która zwraca dane specyficzne dla tej klasy bez konieczności rzutowania na ten obiekt.getClass
jest to lepszy sposób, nie ma biznesu, który zajmuje większość odpowiedzi ;-)Zwykle, gdy chcę poznać rodzaj czegoś, oznacza to, że źle zaimplementowałem strukturę obiektu. W większości przypadków sprowadza się to do naruszenia LSP .
Są jednak chwile, w których chciałbym mieć sposób na dynamiczną wysyłkę i zaoszczędzić mnóstwo kodu płyty kotłowej i zabezpieczyć moją strukturę obiektu na przyszłość. C # zapewnia dynamiczne słowo kluczowe w nowszych wersjach frameworka, ale o ile wiem, Java nadal nie ma czegoś podobnego.
To powiedziawszy, instanceof jest na ogół lepszy niż porównywanie klas, ponieważ odpowiednio obsługuje dziedziczenie. Możesz także użyć metod takich jak isAssignableFrom i inne z interfejsu API reflexion. Jeśli chcesz zaimplementować coś w rodzaju dynamicznej wysyłki, można to zrobić za pomocą interfejsu API odbicia, ale uwaga: będzie ona wolna. Używaj ostrożnie, najlepiej jeśli to możliwe, napraw strukturę obiektu i desing aplikacji.
Mam nadzieję że to pomoże
źródło