Załóżmy, że pracuję na istniejącym, dość dużym systemie. Mam obiekt myObject
klasy MyClass
(dla przykładu załóżmy, że pracuję w Javie). myObject
to kompozycja zawierająca Collection
, powiedzmy, a List
i inne przedmioty, które (myślę) są nieistotne. Zawiera metody delegowania, które służą tylko do wywołania metod, z których List
się składa, w celu zapewnienia, List
że nie zostały ujawnione (przepraszam, jeśli moja błędna terminologia jest nieprawidłowa).
Powiedzmy, że List
jest to, List<String>
ale z jakiegoś powodu główną metodą dostępu jest metoda maskowania klasy SomeOtherClass
. Gdybym chciał wstawić nową parę wartości do siebie List
, miałbym obiekt o SomeOtherClass
nazwie someObject
. Wywołałbym myObject.insert(someObject)
i w insert
metodzie byłaby jakaś magia, która odzyskałaby a String
do włożenia List<String>
.
Załóżmy teraz, że mam tylko String
wartość i nie mam SomeOtherClass
obiektu do wstawienia. Zakładając, że nie mogę zmodyfikować insert
metody, ponieważ zepsułaby wszystko w tym systemie. Czy powinienem przeciążyć insert
metodę? Czy powinienem utworzyć nowy obiekt za SomeOtherClass
każdym razem, gdy chcę zadzwonić insert
?
Wydaje mi się, że gdybym go przeciążył, wyglądałoby to tak ...
public void insert(String s) {
...
}
public void insert(SomeOtherObject obj) {
this.insert(obj.magicStringMethod());
}
(Ten przykład jest wymyśloną łamigłówką opartą na podobnej (nieco bardziej złożonej) sytuacji dotyczącej przeciążenia, z którą się wczoraj spotkałem. Rozwinę ją, jeśli będzie coś niejasnego)
Czy byłoby to odpowiednie miejsce do przeciążenia metody? Jeśli nie, kiedy powinienem przeciążyć metodę?
magicStringMethod()
w moim przykładzie uzyskałbym w moim przypadkuString
reprezentację,SomeOtherObject
która była obiektem domeny.Odpowiedzi:
Przeciążasz, gdy chcesz obsługiwać różne typy:
lub do obsługi progresywnego interfejsu przy użyciu różnych list parametrów:
Możesz nawet trochę zwariować i obsługiwać oba różne typy ORAZ interfejs progresywny, ale powinieneś pamiętać, że musisz unikać tworzenia różnic w zachowaniu między przeciążonymi metodami. Każda przeciążona metoda powinna być funkcjonalnie taka sama jak inne w przeciążonej grupie, w przeciwnym razie nie będzie jasne, jak, kiedy i dlaczego zachowanie się zmienia. Jeśli chcesz, aby dwie funkcje zrobiły coś zupełnie innego, powinieneś odpowiednio je nazwać.
źródło
Powiedziałbym, że przeciążenie jest właściwe, gdy obie metody są semantycznie równoważne. Aby ukraść z przykładów dukeofgaming:
Są one odpowiednio przeciążone:
Te nie są:
Jest to skrajny przykład (jeśli go nie złapałeś, ostatnia metoda faktycznie odejmuje zamiast dodawać), ale pomysł jest taki, że jeśli masz wiele metod w klasie o tej samej nazwie, powinny one zachowywać się konsekwentnie.
W twoim przykładzie z podanych informacji wydają się one równoważne (ponieważ jedno wywołuje drugie) i uważam, że rozsądne byłoby ich przeciążenie. Zapytanie kogoś wyższego szczebla w zespole nie może zaszkodzić, jeśli nie masz pewności, czy metoda powinna zostać dodana, ale jeśli ją dodasz, użyłbym tej samej nazwy (tzn. Przeładowałbym ją).
źródło
Zasadniczo posiadanie parametrów metody decyduje o jej zachowaniu.
Szybki przykład to:
Jeśli przekażesz metodzie sumę (a, b) kilka liczb całkowitych, to wie, że powinna ona wywołać pierwszą implementację, ponieważ wywołanie metody pokrywa się z sygnaturą metody (tj. Podwójna suma (podwójna, podwójna) nie zadziała, jeśli podasz metoda sumy dwie liczby całkowite).
Podpis wywołania musi być zgodny z dostępnymi implementacjami, więc próba wywołania sumy (ciąg, ciąg) nie będzie działać, jeśli nie masz:
tl; dr: Aby klasa obsłużyła poprawną metodę zgodnie z parametrami podanymi dla metody o tej samej nazwie.
Podczas dziedziczenia nazywa się to przesłonięciem
Dobrym przykładem tego innego scenariusza jest sytuacja, w której chcesz zmienić domyślne zachowanie klasy, dziedzicząc ją, a zwłaszcza gdy masz coś podobnego do wzorca metody szablonu , gdzie każdy krok algorytmu jest zaimplementowany w metodzie.
Wyobraź sobie, że masz
class Robot
i metodę o nazwiefireAtTarget(Target target)
... która wywołujefireWeaponA(target); fireWeaponB(target); fireWeaponC(target);
jeden po drugim. Chcesz także mieć kolekcję o nazwie robot_army, do której możesz tylko dodawać obiekty klasy Robot. Robot strzela domyślnie w swojefireWeaponX()
metody karabinami maszynowymi .Więc chcesz mieć
class LazorRobot
iclass MissileRobot
czy wdrażasz Robot od nowa ?, nie, po prostu LazorRobot i MissileRobot odziedziczą Robota i przeciążaj każdąfireWeaponX()
metodę korzystania z Lazorza lub pocisków, a będziesz mieć takie samo zachowanie z inną bronią, bez konieczności ponownej implementacji pozostałe metody.tl; dr: Aby zachowanie metody zależało od klasy bez zerwania interfejsu (robot_army akceptuje tylko Robota, ale przez rozszerzenie akceptuje wszystkie klasy, które dziedziczą Robota).
źródło
when inheriting
sekcja prawdopodobnie nie będzie potrzebna. :)sum(String, String)
asum(int, int)
?