Czy skład i dziedzictwo są takie same? Jeśli chcę zaimplementować wzorzec kompozycji, jak mogę to zrobić w Javie?
java
oop
inheritance
composition
gmhk
źródło
źródło
Odpowiedzi:
Są absolutnie różne. Dziedziczenie to relacja „jest-a” . Kompozycja jest „has-a” .
Komponujesz, mając instancję innej klasy
C
jako pole swojej klasy, zamiast rozszerzaćC
. Dobry przykład, w którym kompozycja byłaby o wiele lepsza niż dziedziczeniejava.util.Stack
, która obecnie się rozszerzajava.util.Vector
. To jest teraz uważane za błąd. Wektor stosu to „NIE-NIE” ; nie powinno się zezwalać na dowolne wstawianie i usuwanie elementów. Zamiast tego powinna to być kompozycja.Niestety jest już za późno, aby naprawić ten błąd projektowy, ponieważ zmiana hierarchii dziedziczenia spowodowałaby uszkodzenie kompatybilności z istniejącym kodem. Gdyby
Stack
używane zamiast kompozycji dziedziczenia, można zawsze modyfikowane, inną strukturę danych bez naruszania API .Bardzo polecam książkę Josha Blocha Effective Java 2nd Edition
Dobry projekt obiektowy nie polega na swobodnym rozszerzaniu istniejących klas. Twoim pierwszym instynktem powinno być komponowanie.
Zobacz też:
źródło
Kompozycja oznacza
HAS A
Dziedziczenie
IS A
Example
: Samochód ma silnik, a samochód to samochódW programowaniu jest to przedstawiane jako:
źródło
:-/
type
pole typuEnum
Jak dziedziczenie może być niebezpieczne?
Weźmy przykład
1) Jak jasno wynika z powyższego kodu, klasa Y ma bardzo silne sprzężenie z klasą X. Jeśli coś zmieni się w nadklasie X, Y może się dramatycznie złamać. Załóżmy, że w przyszłości klasa X implementuje metodę pracy z podpisem poniżej
Zmiany dokonano w klasie X, ale uniemożliwi ona kompilację klasy Y. Tak więc tego rodzaju zależność może wzrosnąć do dowolnego poziomu i może być bardzo niebezpieczna. Za każdym razem, gdy nadklasa może nie mieć pełnej widoczności kodu we wszystkich swoich podklasach, podklasa może ciągle zauważać, co dzieje się w nadklasie. Musimy więc unikać tego silnego i niepotrzebnego połączenia.
Jak kompozycja rozwiązuje ten problem?
Zobaczmy, przeglądając ten sam przykład
Tutaj tworzymy odwołanie do klasy X w klasie Y i wywołujemy metodę klasy X, tworząc instancję klasy X. Teraz całe to silne sprzężenie zniknęło. Nadklasa i podklasa są teraz wysoce od siebie niezależne. Klasy mogą swobodnie dokonywać zmian, które były niebezpieczne w sytuacji spadkowej.
2) Druga bardzo dobra zaleta kompozycji, ponieważ zapewnia elastyczność wywoływania metod, na przykład:
W klasie Test przy użyciu referencji r mogę wywoływać metody klasy X, a także klasy Y. Ta elastyczność nigdy nie była dziedziczona
3) Kolejna wielka zaleta: testowanie jednostkowe
W powyższym przykładzie, jeśli stan instancji x nie jest znany, można go łatwo wykpić przy użyciu niektórych danych testowych, a wszystkie metody można łatwo przetestować. Nie było to możliwe w przypadku dziedziczenia, ponieważ byłeś silnie zależny od nadklasy, aby uzyskać stan instancji i wykonać dowolną metodę.
4) Kolejnym dobrym powodem, dla którego powinniśmy unikać dziedziczenia, jest to, że Java nie obsługuje wielokrotnego dziedziczenia.
Weźmy przykład, aby to zrozumieć:
Dobrze wiedzieć :
kompozycję można łatwo osiągnąć w czasie wykonywania, a dziedziczenie zapewnia jej funkcje w czasie kompilacji
kompozycja jest również znana jako relacja HAS-A, a dziedziczenie jest również znane jako relacja IS-A
Niech więc nawyk zawsze woli preferować kompozycję niż dziedziczenie z różnych powyższych powodów.
źródło
Odpowiedź udzielona przez @Michaela Rodriguesa jest nieprawidłowa (przepraszam; nie jestem w stanie komentować bezpośrednio) i może powodować pewne zamieszanie.
Implementacja interfejsu jest formą dziedziczenia ... kiedy implementujesz interfejs, nie tylko dziedziczysz wszystkie stałe, ale zobowiązujesz obiekt, aby był typu określonego przez interfejs; wciąż jest to relacja „ jest-a ”. Jeśli samochód implementuje funkcję Fillable , samochód „ is-a ” Fillable i może być używany w kodzie wszędzie tam, gdzie chcesz użyć Fillable .
Skład zasadniczo różni się od dziedziczenia. Korzystając z kompozycji, (jak zauważają inne odpowiedzi) tworzysz relację „ ma-a ” między dwoma obiektami, w przeciwieństwie do relacji „ jest-a ”, którą tworzysz, gdy korzystasz z dziedziczenia .
Tak więc z przykładów samochodów w innych pytaniach, gdybym chciał powiedzieć, że samochód ma „zbiornik paliwa”, użyłbym kompozycji w następujący sposób:
Mam nadzieję, że rozwiąże to wszelkie nieporozumienia.
źródło
Dziedziczenie wydobywa relację IS-A . Kompozycja wydobywa relację HAS-A . Wzorzec strategii wyjaśnia, że Kompozycję należy stosować w przypadkach, gdy istnieją rodziny algorytmów definiujących określone zachowanie.
Klasycznym przykładem jest klasa kaczki, która realizuje zachowanie podczas lotu.
W ten sposób możemy mieć wiele klas, które implementują latanie, np .:
Gdyby chodziło o dziedziczenie, mielibyśmy dwie różne klasy ptaków, które realizują funkcję much w kółko. Tak więc dziedziczenie i skład są zupełnie inne.
źródło
Kompozycja jest taka, jak się wydaje - tworzysz obiekt, wkładając części.
EDYCJA reszta odpowiedzi jest błędnie oparta na następującej przesłance.
Dokonuje się tego za pomocą interfejsów.
Na przykład, korzystając z
Car
powyższego przykładu,Zatem za pomocą kilku standardowych elementów teoretycznych możesz zbudować swój obiekt. Twoim zadaniem jest zatem określić, w jaki sposób
House
chroni pasażerów i jakCar
chroni pasażerów.Dziedziczenie jest jak na odwrót. Zaczynasz od pełnego (lub pół-pełnego) obiektu i zamieniasz lub zastępujesz różne bity, które chcesz zmienić.
Na przykład
MotorVehicle
może pochodzić zFuelable
metody iDrive
metody. Możesz opuścić metodę Fuel, ponieważ jest tak samo, ponieważ tankowanie motocykla i samochodu jest takie samo, ale możesz pominąć tęDrive
metodę, ponieważ motocykl jeździ inaczejCar
.Dzięki dziedziczeniu niektóre klasy są już w pełni zaimplementowane, a inne mają metody, które musisz przesłonić. Z Kompozycją nic ci nie jest dane. (ale możesz zaimplementować interfejsy, wywołując metody w innych klasach, jeśli zdarzy się, że coś wokół ciebie leży).
Kompozycja jest postrzegana jako bardziej elastyczna, ponieważ jeśli masz metodę, taką jak iUsesFuel, możesz mieć metodę gdzieś indziej (inna klasa, inny projekt), która martwi się o radzenie sobie z obiektami, które można zatankować, niezależnie od tego, czy jest to samochód, łódka, piec, grill itp. Interfejsy nakazują, aby klasy, które twierdzą, że implementują ten interfejs, faktycznie miały metody, o które chodzi w tym interfejsie. Na przykład,
wtedy możesz mieć metodę gdzie indziej
Dziwny przykład, ale pokazuje, że ta metoda nie dba o to, co się wypełnia, ponieważ obiekt implementuje
iUsesFuel
, można go wypełnić. Koniec opowieści.Jeśli zamiast tego użyjesz dziedziczenia, będziesz potrzebować różnych
FillHerUp
metod,MotorVehicles
aBarbecues
jeśli nie masz jakiegoś dość dziwnego obiektu podstawowego „ObjectThatUsesFuel”, z którego będziesz mógł dziedziczyć.źródło
ThisCase
, a nie wcamelCase
. Dlatego najlepiej nazwać swoje interfejsyIDrivable
itp. Może nie być potrzebne „I”, jeśli poprawnie zgrupujesz wszystkie interfejsy w pakiet.Nie są takie same.
Kompozycja : umożliwia traktowanie grupy obiektów w taki sam sposób jak pojedynczej instancji obiektu. Celem kompozytu jest „komponowanie” obiektów w struktury drzewne w celu reprezentowania częściowych hierarchii
Dziedziczenie : klasa dziedziczy pola i metody ze wszystkich swoich nadklas, zarówno bezpośrednich, jak i pośrednich. Podklasa może zastępować odziedziczone metody lub ukrywać dziedziczone pola lub metody.
Artykuł w Wikipedii jest wystarczająco dobry, aby zaimplementować wzór złożony w Javie.
Kluczowi uczestnicy:
Komponent :
Liść :
Kompozytowe :
Przykład kodu, aby zrozumieć wzór złożony :
wynik:
Wyjaśnienie:
Zobacz poniższe pytanie za i przeciw składowi i dziedziczeniu.
Wolisz kompozycję niż dziedziczenie?
źródło
jako kolejny przykład rozważ klasę samochodów, byłoby to dobre wykorzystanie składu, samochód „miałby” silnik, skrzynię biegów, opony, siedzenia itp. Nie rozszerzyłby żadnej z tych klas.
źródło
Kompozycja polega na tym, że coś składa się z odrębnych części i ma z nimi silny związek. Jeśli główna część umiera, podobnie jak inni, nie mogą mieć własnego życia. Szorstkim przykładem jest ludzkie ciało. Wyjmij serce, a wszystkie pozostałe części zginą.
Dziedziczenie polega na zabraniu czegoś, co już istnieje, i wykorzystaniu go. Nie ma silnego związku. Człowiek może odziedziczyć majątek ojca, ale może się bez niego obejść.
Nie znam Java, więc nie mogę podać przykładu, ale mogę wyjaśnić pojęcia.
źródło
Dziedziczenie między dwiema klasami, gdzie jedna klasa rozszerza inną klasę, ustanawia relację „ JEST A ”.
Kompozycja na drugim końcu zawiera instancję innej klasy w twojej klasie, która ustanawia relację „ Ma A ”. Składanie w java jest przydatne, ponieważ technicznie ułatwia wielokrotne dziedziczenie.
źródło
W uproszczeniu agregacja słów oznacza związek ma związek.
Kompozycja jest szczególnym przypadkiem agregacji . W bardziej szczegółowy sposób ograniczona agregacja nazywana jest kompozycją. Jeśli obiekt zawiera drugi obiekt, jeśli zawarty obiekt nie może istnieć bez istnienia obiektu kontenera, wówczas nazywa się to kompozycją. Przykład: klasa zawiera uczniów. Uczeń nie może istnieć bez zajęć. Istnieje kompozycja między klasą a uczniami.
Dlaczego warto korzystać z agregacji
Kod wielokrotnego użytku
Kiedy użyj agregacji
Ponowne użycie kodu można najlepiej osiągnąć poprzez agregację, gdy nie ma statku relacji
Dziedzictwo
Dziedziczenie jest rodzicielskim związkiem dziecięcym. Dziedziczenie oznacza relację
Dziedziczenie w java jest mechanizmem, w którym jeden obiekt nabywa wszystkie właściwości i zachowania obiektu nadrzędnego.
Korzystanie z dziedziczenia w wielokrotnym użyciu kodu Java 1. 2 Dodaj dodatkową funkcję w klasie podrzędnej, a także nadpisywanie metod (aby osiągnąć polimorfizm w czasie wykonywania).
źródło
Chociaż zarówno Dziedziczenie, jak i Kompozycja zapewniają możliwość ponownego użycia kodu, główna różnica między Kompozycją a Dziedziczeniem w Javie polega na tym, że Composition umożliwia ponowne użycie kodu bez rozszerzania go, ale w przypadku Dziedziczenia należy rozszerzyć klasę w celu ponownego użycia kodu lub funkcjonalności. Inną różnicą wynikającą z tego faktu jest to, że używając Composition można ponownie użyć kodu nawet dla końcowej klasy, która nie jest rozszerzalna, ale Dziedziczenie nie może ponownie użyć kodu w takich przypadkach. Również za pomocą Composition możesz ponownie użyć kodu z wielu klas, ponieważ są one zadeklarowane jako zmienne składowe, ale dzięki Dziedziczeniu możesz ponownie użyć kodu z jednej klasy, ponieważ w Javie możesz rozszerzyć tylko jedną klasę, ponieważ wielokrotne Dziedziczenie nie jest obsługiwane w Javie . Możesz to zrobić w C ++, ponieważ jedna klasa może rozszerzyć więcej niż jedną klasę. BTW, zawsze powinieneśwolę Kompozycję niż Dziedziczenie w Javie , to nie tylko ja, ale nawet Joshua Bloch zasugerował w swojej książce
źródło
Myślę, że ten przykład jasno wyjaśnia różnice między spadkiem a kompozycją .
W tym przykładzie problem został rozwiązany za pomocą dziedziczenia i składu. Autor zwraca uwagę na fakt, że; w dziedziczeniu zmiana nadklasy może powodować problemy w klasie pochodnej, która ją dziedziczy.
Tam możesz również zobaczyć różnicę w reprezentacji, gdy używasz UML do dziedziczenia lub kompozycji.
http://www.javaworld.com/article/2076814/core-java/inheritance-versus-composition--which-one-should-you-choose-.html
źródło
Dziedziczenie a skład.
Zarówno dziedzictwo, jak i kompozycja są wykorzystywane do ponownego wykorzystania i rozszerzenia zachowania klasowego.
Dziedziczenia stosowane głównie w modelu programowania algorytmów rodzinnych, takim jak typ relacji IS-A, oznacza podobny rodzaj obiektu. Przykład.
Należą one do rodziny samochodów.
Kompozycja reprezentuje typ relacji HAS-A. Pokazuje zdolność obiektu, takiego jak Duster ma pięć przekładni, Safari ma cztery przekładnie itp. Ilekroć musimy rozszerzyć zdolność istniejącej klasy, użyj kompozycji. Przykład: musimy dodać jeszcze jeden sprzęt do obiektu Duster, a następnie musimy utworzyć jeszcze jeden obiekt Gear i skomponować go do obiektu Duster.
Nie powinniśmy wprowadzać zmian w klasie bazowej, dopóki wszystkie klasy pochodne nie będą potrzebować tej funkcjonalności. W tym scenariuszu powinniśmy użyć Composition.Such
klasa A Pochodzi z klasy B
Klasa A Pochodzi z klasy C.
Klasa A Pochodzi z klasy D.
Gdy dodamy dowolną funkcjonalność w klasie A, będzie ona dostępna dla wszystkich podklas, nawet jeśli klasy C i D nie wymagają tej funkcjonalności. W tym scenariuszu musimy utworzyć osobną klasę dla tych funkcji i skomponować ją do wymaganej klasy ( tutaj jest klasa B).
Poniżej znajduje się przykład:
źródło
Kompozycja oznacza utworzenie obiektu dla klasy, która ma związek z tą konkretną klasą. Załóżmy, że uczeń ma związek z kontami;
Dziedziczeniem jest, to jest poprzednia klasa z rozszerzoną funkcją. Oznacza to, że ta nowa klasa jest klasą starą z pewnymi rozszerzonymi funkcjami. Załóżmy, że uczeń jest uczniem, ale wszyscy uczniowie są ludźmi. Więc istnieje związek ze studentem i człowiekiem. To jest dziedziczenie.
źródło
Nie, oba są różne. Kompozycja podąża za relacją „HAS-A”, a dziedzictwo podąża za relacją „IS-A”. Najlepszym przykładem kompozycji był wzór strategiczny.
źródło
Dziedziczenie oznacza ponowne wykorzystanie pełnej funkcjonalności klasy. Tutaj moja klasa musi korzystać ze wszystkich metod superklasy, a moja klasa będzie dosłownie sprzężona z superklasą, a kod zostanie zduplikowany w obu klasach w przypadku dziedziczenia.
Ale możemy rozwiązać ten problem, używając kompozycji do rozmowy z inną klasą. Skład deklaruje atrybut innej klasy w mojej klasie, z którą chcemy porozmawiać. i jakiej funkcjonalności chcemy od tej klasy możemy uzyskać za pomocą tego atrybutu.
źródło