Składanie ma miejsce, gdy klasa oferuje pewną funkcjonalność, tworząc instancję (być może wewnętrzną) klasy, która już implementuje tę funkcjonalność, zamiast dziedziczenia po tej klasie.
Na przykład, jeśli masz klasę, która modeluje statek, a powiedziano ci teraz, że twój statek powinien oferować lądowisko dla helikopterów, nie jest naturalne wyprowadzanie statku z lądowiska dla helikopterów (duh!), Zamiast tego powinieneś twój statek zawiera klasę lądowisk dla helikopterów i wystawiasz go jakąś Ship.getHelipad()
metodą.
W dawnych latach (mniej więcej dziesięć lat temu) ludzie postrzegali dziedziczenie jako szybki i łatwy sposób na agregowanie funkcjonalności, więc było wiele przykładów rodzaju „statku dziedziczącego po lądowisku dla helikopterów”, które były oczywiście bardzo kiepskie.
Ale powiedzenie „Preferuj kompozycję nad dziedziczeniem” zostało starannie sformułowane, aby wyjaśnić, że jest to tylko sugestia, a nie reguła. Autor powiedzenia był na tyle ostrożny, by powstrzymać się od powiedzenia czegoś w rodzaju „ nigdy nie będziesz używać dziedzictwa, tylko kompozycji”. Zasadniczo zwraca to uwagę społeczności inżynierów oprogramowania na fakt, że dziedziczenie zostało nadużywane, podczas gdy w wielu przypadkach kompozycja zapewnia bardziej przejrzyste, eleganckie i łatwe do utrzymania projekty niż dziedziczenie.
Zasadniczo więc powiedzenie „Faworyzuj kompozycję nad dziedziczeniem” sugeruje, że ilekroć masz do czynienia z „dziedziczeniem czy komponowaniem”? pytanie, powinieneś mocno przemyśleć, jaka jest najbardziej odpowiednia strategia, i że istnieje największe prawdopodobieństwo, że najbardziej odpowiednią strategią okaże się kompozycja, a nie dziedziczenie.
Ale ponieważ nie jest to regułą, należy również pamiętać, że w wielu przypadkach dziedziczenie jest bardziej naturalne. Jeśli użyjesz kompozycji tam, gdzie powinieneś był użyć dziedziczenia, wiele zła spotka Twój kod.
Wracając do przykładu statku, jeśli twój statek musi oferować interfejs do interakcji z a FloatingMachine
, bardziej naturalne jest wyprowadzenie go z FloatingMachine
klasy abstrakcyjnej , która z kolei prawdopodobnie mogłaby pochodzić z innej Machine
klasy abstrakcyjnej .
Oto ogólna zasada dla odpowiedzi na pytanie dotyczące składu a pytanie dotyczące dziedziczenia:
Czy moja klasa ma relację „jest” z interfejsem, który musi ujawnić? Jeśli tak, użyj dziedziczenia. Jeśli nie, użyj kompozycji.
Statek „to„ maszyna pływająca, a maszyna pływająca ”to„ maszyna. Tak więc dziedziczenie jest dla nich w porządku. Ale statek nie jest oczywiście lądowiskiem dla helikopterów. Lepiej więc skomponuj funkcjonalność lądowiska dla helikopterów.