Trochę jest, bo kiedy piszę class Human extends Animal
to mówię że Human
JEST Animal
em. W przypadku kompozycji takiej relacji nie ma.
To jest właśnie klasyczny akademicki przykład błędnego dziedziczenia i błędnego myślenia o dziedziczeniu. Dziedziczenie nie powinno być używane do tworzenia kategorii obiektów lecz do organizacji kodu.
Czemu tej logiki która jest w klasie bazowej też nie wstrzyknąć?
Ależ przecież można ją wstrzyknąć i używać w klasie bazowej. Ja nie widzę problemu, dopóki ma to sens.
Odpowiedziałem na Twój argument że "injectowanie klasy bazowej z kontenera jest bez związku".
Jest bez związku, bo klas bazowych się nie wstrzykuje, z nich się po prostu dziedziczy.
To co Ty robisz, to próba udowodnienia, że samochód jest lepszy od roweru, bo do roweru nie ma gdzie nalać paliwa. A to przecież oczywiste, bo rower nie potrzebuje paliwa.
Chciałem powiedzieć że dobrze byłoby, że jeśli ktoś korzysta z kontenerów zależności, żeby mógł z tego kontenera wyciągać którą implementację chcę. Jeśli mamy klasę class A extends Baza
, i chce korzystać z logiki A
ale Baza
chce zamienić na Baza2
, cóż nie ma szczęścia.
O ile brak projektu to brak szczęścia. ;) Klasa bazowa ma sens w celu uniknięcia duplikacji pewnych szczegółów implementacji, a nie w celu budowy kodu dającego się podmienić w locie.
Ale metoda szablonowa nie mówi nic o tym czy szczegóły implementacyjne mają być dostarczane przez klasy-dzieci czy przez wstrzykniętą implementację interfejsu.
W definicji podanej w Twoim linku masz istnienie klas bazowych i dziedziczenia: It consists of leaving some abstract methods in a base class to be implemented in derived specialized classes.
Ten wzorzec jest oparty o dziedziczenie i tyle. To, czy jakieś operacje zostaną oddelegowane, czy będą fizycznie w klasie bazowej to kolejny szczegół implementacyjny.
W odpowiedzi, wracam do mojej poprzedniej odpowiedzi:
Ale jakie to ma znaczenie?
Masz klasy: A
, B
i C
, które mają jakieś publiczne metody. Metody te mają być przetestowane bez znaczenia, czy pod spodem jest jakiś kod, który się wykona wiele razy, czy nie, czy mają wspólną klasę bazową, czy nie, czy mają jakieś zależności, czy nie.
Testuje się to, co kod robi, a nie jego strukturę.
Nie powiecie mi, że to jest nieprawidłowa abstrakcyjna klasa bazowa. Tutaj np. do testowania jest DeepClone.
No jest nieprawidłowa - publiczne DeepClone
nie ma sensu, bo nie można go wywołać na obiekcie klasy, w której się znajduje.A skoro nie da się jej użyć, to nie ma też po co jej testować.
Taka metoda ma sens tylko jeśli jest protected
i używana przez klasy potomne.
Jak na razie wymieniłem bardzo dużo powodów dla których ktoś miałby wybrać kompozycję, ale nie poznałem żadnego czemu ktoś miałby preferować dziedziczenie?
Ja po prostu nie uznaję czegoś takiego jak "preferuję kompozycję" czy "preferuję dziedziczenie". Kompozycja ma swoje zastosowania, dziedziczenie swoje. Jeśli ktoś coś "preferuje" i zastępuje prawidłowy kod tym "preferowanym", to najprawdopodobniej efekty są słabe.
Jeśli Ty w ogóle nie używasz dziedziczenia, to jest spore prawdopodobieństwo, że są sytuacje, w których piszesz kod bardziej skomplikowany niż to konieczne, albo nie używasz sensownych wzorców.
Kompozycja nie jest darmowa - trzeba jakoś tworzyć i/lub przekazywać obiekty. Jest dodatkowy kod do utrzymania, bardziej rozbudowane konstruktory, itd. W przypadku kilku linijek kodu operujących na stanie obiektu to często może być gra nie warta świeczki. Wszystko zależy od sytuacji.