JavaRush /Blog Java /Random-PL /Przerwa kawowa #95. Jak rozwiązać problem wielokrotnego d...

Przerwa kawowa #95. Jak rozwiązać problem wielokrotnego dziedziczenia w Javie

Opublikowano w grupie Random-PL
Źródło: FreeCodeCamp Java to jeden z najpopularniejszych obecnie używanych obiektowych języków programowania. Ponieważ jest niezależny od platformy, aplikacje Java można znaleźć na każdym typie urządzenia i każdym systemie operacyjnym. A ponieważ Java jest stosunkowo łatwa do nauczenia, jest to jeden z języków, który zna wielu programistów. Ważną cechą języka Java, z którą powinieneś się zapoznać, jest dziedziczenie klas. Dziedziczenie pozwala zoptymalizować kod, ułatwiając ponowne wykorzystanie klas. Kiedy możesz ponownie wykorzystać kod, który został już przetestowany i zdebugowany, cykl życia oprogramowania staje się krótszy i tańszy. Przerwa kawowa #95.  Jak rozwiązać problem wielokrotnego dziedziczenia w Javie - 1Chociaż w teorii jest to prosta koncepcja, kodowanie relacji dziedziczenia wymaga dbałości o szczegóły. Zwłaszcza w odniesieniu do dziedziczenia wielokrotnego, gdzie jedna klasa podrzędna dziedziczy właściwości z wielu klas nadrzędnych. Java odrzuca relacje wielokrotnego dziedziczenia, ponieważ powodują one niejednoznaczność, ale istnieje kilka sposobów na osiągnięcie wielu takich samych efektów, jeśli wiesz, co robić. W tym artykule przyjrzymy się problemom związanym z dziedziczeniem wielokrotnym i omówimy alternatywne opcje kodowania w Javie.

Terminologia dotycząca dziedziczenia

Czasami, aby odnieść sukces jako programista, musisz umieć rozwiązywać problemy i znajdować obejścia typowych błędów i problemów. Jest to istotna część bezpiecznego i inteligentnego kodowania. Jeden z takich problemów jest związany z wielokrotnym dziedziczeniem (a raczej jego brakiem) w Javie. Przerwa kawowa #95.  Jak rozwiązać problem wielokrotnego dziedziczenia w Javie - 2Aby w pełni zrozumieć dziedziczenie w Javie, musisz znać podstawową terminologię dotyczącą dziedziczenia w programowaniu obiektowym (OOP).
  • Klasy są podstawową strukturą wzorców w obiektowych językach programowania. Klasa definiuje wspólne właściwości grupy obiektów.
  • Klasa nadrzędna : znana również jako klasy bazowe lub superklasy. Klasa nadrzędna jest klasą rozszerzalną, która zapewnia funkcjonalność klasie podrzędnej. Pozwala na ponowne wykorzystanie. Definicje i funkcje klasy nadrzędnej są ponownie wykorzystywane podczas tworzenia klas podrzędnych.
  • Klasa podrzędna : bardziej ogólnie nazywana podklasą, klasa podrzędna dziedziczy funkcjonalność z innej klasy. Klasy podrzędne są klasami rozszerzonymi lub pochodnymi.
  • Dziedziczenie : Relacja pomiędzy klasami nadrzędnymi i podrzędnymi.

Typy dziedziczenia OOP

Obecnie w użyciu jest wiele popularnych obiektowych języków programowania, w tym Java, C++, JavaScript, Python, PHP, Ruby i Perl. Chociaż dziedziczenie jest powszechną koncepcją w tych językach OOP, nie wszystkie typy dziedziczenia istnieją w każdym z tych języków. Niezwykle ważna jest znajomość powszechnych rodzajów dziedziczenia i ograniczeń dziedziczenia w konkretnym języku, którego używasz. Im więcej wiesz o dziedziczeniu, tym skuteczniejszym programistą się staniesz. Rodzaje dziedziczenia obsługiwane przez Javę obejmują:
  • Dziedziczenie jednopoziomowe : gdy klasa podrzędna dziedziczy funkcje z pojedynczej klasy nadrzędnej.
  • Dziedziczenie wielopoziomowe : Jest to wielopoziomowa forma dziedziczenia jednopoziomowego. W przypadku dziedziczenia wielopoziomowego klasa podrzędna może również pełnić funkcję klasy nadrzędnej dla innych klas podrzędnych. Zależność pomiędzy każdym poziomem jest liniowa – żadne gałęzie nie wznoszą się wyżej niż w przypadku dziedziczenia wielokrotnego. W tym przypadku ostatnia klasa potomna zawiera funkcje ze wszystkich poziomów powyżej.
  • Dziedziczenie hierarchiczne : przeciwieństwo dziedziczenia wielokrotnego. W dziedziczeniu hierarchicznym pojedyncza klasa nadrzędna ma więcej niż jedną klasę podrzędną. Zamiast mieć gałęzie nad sobą, rozgałęzia się poniżej.
  • Dziedziczenie hybrydowe : Jak sama nazwa wskazuje, dziedziczenie hybrydowe to połączenie innych typów dziedziczenia.
Oprócz wymienionych powyżej typów dziedziczenia istnieją inne typy, których Java nie obsługuje.
  • Dziedziczenie wielokrotne : w przypadku dziedziczenia wielokrotnego klasa podrzędna ma więcej niż jedną klasę nadrzędną. Chociaż Java i JavaScript nie obsługują dziedziczenia wielokrotnego, języki OOP, takie jak C++, tak.
  • Dziedziczenie wielościeżkowe : hybryda dziedziczenia wielokrotnego, wielopoziomowego i hierarchicznego. W przypadku dziedziczenia wielościeżkowego klasa potomna dziedziczy swoje cechy i funkcje od klasy nadrzędnej i kilku klas podrzędnych klasy nadrzędnej. Ponieważ dziedziczenie wielościeżkowe opiera się na dziedziczeniu wielokrotnym, Java nie obsługuje jego użycia.

Dlaczego Java nie obsługuje wielokrotnego dziedziczenia

Głównym problemem związanym z dziedziczeniem wielokrotnym jest to, że może ono powodować niejasności w klasach potomnych. W białej księdze z 1995 roku główny projektant Java James Gosling stwierdził, że problemy z wielokrotnym dziedziczeniem były jednym z powodów stworzenia Java. Złożoność nieodłącznie związana z dziedziczeniem wielokrotnym jest najwyraźniej widoczna w problemie diamentu. W problemie diamentu klasa nadrzędna A ma dwie różne klasy podrzędne B i C; to znaczy klasy potomne B i C rozszerzają klasę A. Przerwa kawowa #95.  Jak rozwiązać problem wielokrotnego dziedziczenia w Javie - 3Teraz tworzymy nową klasę potomną D, która rozszerza zarówno klasę B, jak i klasę C. Zauważ, że mamy dziedziczenie wielokrotne (D rozszerza B i C), dziedziczenie hierarchiczne ( B i C rozszerzają A) i dziedziczenie wielopoziomowe (D rozszerza A, B i C). W przypadku problemu z diamentem klasy potomne B i C dziedziczą metodę z klasy nadrzędnej A. Zarówno B, jak i C zastępują dziedziczoną metodę. Ale nowe metody w B i C są ze sobą sprzeczne. Ostateczna klasa potomna D dziedziczy dwie niezależne i sprzeczne metody od swoich wielokrotnych rodziców B i C. Nie jest jasne, która metoda klasy D powinna zostać zastosowana, co powoduje niejasność. Inne języki programowania OOP wdrażają różne metody rozwiązywania niejednoznaczności wielokrotnego dziedziczenia.

Jak rozwiązać problem wielokrotnego dziedziczenia w Javie

To, że dziedziczenie wielokrotne jest problematyczne, nie oznacza, że ​​jest bezużyteczne. Istnieje wiele sytuacji, w których możesz chcieć, aby jedna klasa miała funkcje z kilku innych klas. Pomyśl tylko o Tesli Roadster, którą kupisz, gdy odniesiesz ogromny sukces jako programista. Jego parametry techniczne opierają się zarówno na klasie samochodu sportowego, jak i klasie pojazdu elektrycznego. Inny przykład: przeglądarka, przez którą czytasz ten artykuł. Posiada funkcje z klasy rozwiązań dotyczących prywatności w Internecie i z ogólnej klasy przeglądarek internetowych. Ale nie można rozszerzać wielu klas w Javie. Jak zatem ten język radzi sobie z problemem wielokrotnego dziedziczenia? Java wykorzystuje struktury zwane interfejsami. Interfejsy to typy abstrakcyjne, które definiują zachowanie, które ma być implementowane przez klasy. Ponieważ są abstrakcyjne, interfejsy nie zawierają szczegółowych instrukcji dotyczących ich zachowania. Zamiast tego klasy zapewniają konkretne implementacje zachowań interfejsu. Interfejsy mają kilka charakterystycznych cech:
  • W przeciwieństwie do klas, nie tworzy się instancji interfejsów. Zamiast tego klasy implementują interfejsy.
  • Interfejsy zawierają tylko publiczne definicje stałych i nagłówki metod.
  • Interfejsy mogą rozszerzać jedynie inne interfejsy, a nie klasy.
  • Interfejsy mogą rozszerzać wiele interfejsów, a klasy mogą implementować wiele interfejsów.
Możemy teraz skutecznie obejść problem diamentów za pomocą interfejsów. Pamiętając, że tylko interfejsy mogą rozszerzać tylko inne interfejsy, a każda klasa wymagająca cech wielokrotnego dziedziczenia musi implementować wiele interfejsów, możemy zastąpić klasy problemów diamentowych. To, co kiedyś było klasami A, B i C, stało się teraz interfejsami A, B i C. Interfejsy B i C nadal rozszerzają interfejs A, ale żaden z tych interfejsów nie ma określonej funkcjonalności, a jedynie określone zachowania. Klasa D pozostaje klasą odpowiedzialną za specyficzną implementację zachowania interfejsów B i C. Zwróć uwagę na jedną kluczową różnicę: klasa D nie rozszerza interfejsów B i C. Zamiast tego je implementuje. W ten sposób w rzeczywistości nie masz wielokrotnego dziedziczenia. Zamiast tego po prostu przeformułowałeś problem.

Wniosek

Zrozumienie dziedziczenia jest niezbędne dla każdego skutecznego programisty Java. Równie ważna jest znajomość ograniczeń dziedziczenia i wbudowanych w Javę sposobów obejścia tradycyjnych problemów z wielokrotnym dziedziczeniem. Nauczenie się, jak tworzyć interfejsy umożliwiające odtworzenie efektów wielokrotnego dziedziczenia w języku Java, poprawi Twoją produktywność i możliwości zatrudnienia.
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION