Dobre powody, aby zakazać dziedziczenia w Javie?

Jakie są dobre powody, aby zabronić dziedziczenia w Javie, na przykład poprzez użycie klasy końcowej lub klas używających pojedynczego, prywatnego konstruktora bez parametru? Jakie są dobre powody, aby metoda była ostateczna?

Author: cretzel, 2008-10-20

11 answers

Najlepszym punktem odniesienia jest pozycja 19 znakomitej książki Joshuy Blocha "Effective Java", zatytułowanej "Design and document for inheritance or else". (Pozycja 17 w drugim wydaniu i pozycja 15 W pierwszym wydaniu. Naprawdę powinieneś to przeczytać, ale streszczę.

Interakcja klas dziedzicznych z ich rodzicami może być zaskakująca i nieprzewidywalna, jeśli przodek nie został zaprojektowany do dziedziczenia.

Klasy powinny więc występować w dwóch rodzajach :

  1. Klasy przeznaczone do rozszerzone, i z wystarczającą dokumentacją, aby opisać, jak należy to zrobić

  2. Klasy oznaczone finał

Jeśli piszesz czysto wewnętrzny kod, może to być trochę przesada. Jednak dodatkowy wysiłek związany z dodaniem pięciu znaków do pliku klasy jest bardzo mały. Jeśli piszesz tylko dla wewnętrznego komsumpcji to przyszły koder zawsze może usunąć "ostateczny" - ty można o tym myśleć jako ostrzeżenie, mówiąc :" ta klasa nie została zaprojektowana z myślą o dziedziczeniu".

 150
Author: DJClayworth,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-23 13:21:48

Możesz chcieć, aby metoda była ostateczna, aby nadpisujące klasy nie mogły zmienić zachowania, które są liczone w innych metodach. Metody wywoływane w konstruktorach są często deklarowane jako ostateczne, więc nie można spodziewać się przykrych niespodzianek podczas tworzenia obiektów.

 21
Author: Bill the Lizard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-20 15:10:05

Jednym z powodów, aby zrobić finał klasy byłoby, gdybyś chciał wymusić skład ponad dziedziczenie. Jest to ogólnie pożądane w unikaniu ciasnego łączenia między klasami.

 15
Author: John Topley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-20 15:11:54

Możesz chcieć tworzyć obiekty niezmienne ( http://en.wikipedia.org/wiki/Immutable_object ), możesz utworzyć singleton ( http://en.wikipedia.org/wiki/Singleton_pattern ), lub może chcesz uniemożliwić komuś nadpisanie metody ze względu na wydajność, bezpieczeństwo lub ochronę.

 12
Author: Ray Tayek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-20 15:21:05

Istnieją 3 przypadki użycia, w których można przejść do ostatecznych metod.

  1. aby uniknąć nadpisywania określonej funkcji klasy bazowej przez klasę pochodną.
  2. jest to dla celów bezpieczeństwa, gdzie klasa bazowa daje jakąś ważną podstawową funkcjonalność frameworka, gdzie klasa pochodna nie powinna jej zmieniać.
  3. Metody końcowe są szybsze niż metody instancyjne, ponieważ nie ma zastosowania koncepcja tabeli wirtualnej dla metod końcowych i prywatnych. Więc gdzie kiedykolwiek jest możliwość, spróbuj użyć ostatecznych metod.

Cel utworzenia klasy końcowej:

Aby żadne ciało nie mogło rozszerzyć tych klas I zmienić ich zachowanie.

Np: wrapper class Integer jest klasą końcową. Jeśli ta klasa nie jest ostateczna, wtedy każdy może rozszerzyć Integer do swojej własnej klasy I zmienić podstawowe zachowanie klasy integer. Aby tego uniknąć, java stworzyła wszystkie klasy wrapperów jako klasy końcowe.

 12
Author: user1923551,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-10 15:47:03

Dziedziczenie jest jak piła łańcuchowa - bardzo potężne, ale straszne w niewłaściwych rękach. Albo zaprojektujesz klasę, która ma być dziedziczona (co może ograniczyć elastyczność i trwać znacznie dłużej) , albo powinieneś ją zakazać.

Zobacz Effective Java 2nd edition poz. 16 i 17, lub mój wpis na blogu "podatek od spadków" .

 6
Author: Jon Skeet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-22 05:46:05

Hmmm... Mogę myśleć o dwóch rzeczach:

Możesz mieć klasę, która zajmuje się pewnymi kwestiami bezpieczeństwa. Poprzez podklasowanie go i podawanie systemowi podklasowanej wersji, atakujący może obejść ograniczenia bezpieczeństwa. Np. Twoja aplikacja może obsługiwać wtyczki, a jeśli wtyczka może po prostu podklasować Twoje klasy związane z bezpieczeństwem, może użyć tej sztuczki, aby w jakiś sposób przemycić podklasowaną wersję na miejsce. Jest to jednak raczej coś, z czym Sun ma do czynienia w odniesieniu do aplety i tym podobne, może nie taki realistyczny przypadek. O wiele bardziej realistyczne jest unikanie, by obiekt stał się zmienny. Np. ponieważ ciągi znaków są niezmienne, Twój kod może bezpiecznie przechowywać odniesienia do niego
 String blah = someOtherString;

Zamiast najpierw kopiować ciąg znaków. Jednak, jeśli możesz podklasować Łańcuch, możesz dodać do niego metody, które pozwalają na modyfikację wartości łańcucha, teraz żaden kod nie może już polegać na tym, że łańcuch pozostanie taki sam, jeśli tylko skopiuje łańcuch jak powyżej, zamiast tego musi się zduplikować sznurek.

 4
Author: Mecki,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-20 15:13:05

Aby powstrzymać ludzi przed robieniem rzeczy, które mogłyby zmylić siebie i innych. Wyobraź sobie bibliotekę fizyki, w której masz określone stałe lub obliczenia. Bez użycia ostatniego słowa kluczowego ktoś mógłby przyjść i przedefiniować podstawowe obliczenia lub stałe, które nigdy nie powinny się zmieniać.

 1
Author: Anson Smith,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-20 15:12:21

Ponadto, jeśli piszesz komercyjną klasę zamkniętego Źródła, możesz nie chcieć, aby ludzie mogli zmieniać funkcjonalność w dół linii, zwłaszcza jeśli musisz dać wsparcie dla niej i ludzie mają nadpisane metody i narzekają, że wywołanie jej daje nieoczekiwane wyniki.

 1
Author: DavidG,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-20 15:51:01

Jeśli oznaczasz klasy i metody jako ostateczne, możesz zauważyć niewielki wzrost wydajności, ponieważ runtime nie musi szukać właściwej metody klasy, aby wywołać dany obiekt. Niekończące się metody są oznaczone jako wirtualne, dzięki czemu mogą być odpowiednio rozszerzone w razie potrzeby, końcowe metody mogą być bezpośrednio połączone lub skompilowane w linii w klasie.

 1
Author: seanalltogether,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-20 17:35:31

Chcesz, aby metoda była ostateczna, aby nadpisujące klasy nie zmieniały jej zachowania. Jeśli chcesz mieć możliwość zmiany zachowania, upublicznij metodę. Po nadpisaniu metody publicznej można ją zmienić.

 0
Author: Alexander Robinson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-10 21:29:14