Im więcej dowiaduję się o różnych paradygmatach programowania, takich jak programowanie funkcjonalne, tym bardziej zaczynam kwestionować mądrość koncepcji OOP, takich jak dziedziczenie i polimorfizm. Po raz pierwszy dowiedziałem się o dziedziczeniu i polimorfizmie w szkole, a polimorfizm wydawał się wtedy wspaniałym sposobem na pisanie kodu ogólnego, który pozwalał na łatwą rozszerzalność.
Ale w obliczu pisania kaczego (zarówno dynamicznego, jak i statycznego) oraz funkcji takich jak funkcje wyższego rzędu, zacząłem patrzeć na dziedziczenie i polimorfizm jako narzucanie niepotrzebnych ograniczeń opartych na kruchym zestawie relacji między obiektami. Ogólna idea polimorfizmu polega na tym, że piszesz funkcję raz, a później możesz dodać nową funkcjonalność do swojego programu bez zmiany pierwotnej funkcji - wszystko, co musisz zrobić, to stworzyć kolejną klasę pochodną, która implementuje niezbędne metody.
Ale jest to o wiele łatwiejsze do osiągnięcia przez pisanie kaczych, czy to w dynamicznym języku, takim jak Python, czy w języku statycznym, takim jak C ++.
Jako przykład weźmy pod uwagę następującą funkcję Python, a następnie jej statyczny odpowiednik C ++:
def foo(obj):
obj.doSomething()
template <class Obj>
void foo(Obj& obj)
{
obj.doSomething();
}
Odpowiednik OOP byłby podobny do następującego kodu Java:
public void foo(DoSomethingable obj)
{
obj.doSomething();
}
Główną różnicą jest oczywiście to, że wersja Java wymaga utworzenia interfejsu lub hierarchii dziedziczenia, zanim będzie działać. Wersja Java wymaga zatem więcej pracy i jest mniej elastyczna. Ponadto uważam, że większość rzeczywistych hierarchii dziedziczenia jest nieco niestabilna. Wszyscy widzieliśmy wymyślone przykłady kształtów i zwierząt, ale w prawdziwym świecie, gdy zmieniają się wymagania biznesowe i dodaje się nowe funkcje, trudno jest wykonać jakąkolwiek pracę, zanim naprawdę trzeba rozciągnąć relację „to-a” między podklasy, albo przebuduj / przebuduj swoją hierarchię, aby uwzględnić dodatkowe klasy podstawowe lub interfejsy w celu dostosowania do nowych wymagań. Dzięki pisaniu kaczek nie musisz się martwić o modelowanie - po prostu martwisz się o potrzebną funkcjonalność .
Jednak dziedziczenie i polimorfizm są tak popularne, że wątpię, czy nazwanie ich dominującą strategią rozszerzalności i ponownego użycia kodu byłoby przesadą. Dlaczego więc dziedziczenie i polimorfizm są tak szalenie skuteczne? Czy pomijam jakieś poważne zalety dziedziczenia / polimorfizmu w porównaniu z pisaniem kaczek?
objnie byłodoSomethingmetody? Czy zgłoszono wyjątek? Czy nic się nie dzieje