Czy klasa powinna wiedzieć o swoich podklasach? Czy klasa powinna na przykład zrobić coś specyficznego dla danej podklasy?
Mój instynkt podpowiada mi, że jest to zły projekt, wydaje się być pewnego rodzaju anty-wzorem.
Czy klasa powinna wiedzieć o swoich podklasach? Czy klasa powinna na przykład zrobić coś specyficznego dla danej podklasy?
Mój instynkt podpowiada mi, że jest to zły projekt, wydaje się być pewnego rodzaju anty-wzorem.
Odpowiedzi:
Odpowiedź sugerowana przez pojęcie klas brzmi „nie”.
Niezależnie od tego, jaką akcję, dane lub relację wykonujesz, należy ona do wszystkich podklas - wtedy powinna być obsługiwana w nadklasie bez sprawdzania rzeczywistego typu. Lub odnosi się tylko do niektórych podklas - wtedy trzeba by wykonać sprawdzanie typu w czasie wykonywania, aby zrobić właściwą rzecz, nadklasa musiałaby zostać zmieniona za każdym razem, gdy ktoś inny odziedziczy po niej (lub może po cichu zrobić coś niewłaściwego), zmiany w klasach pochodnych mogą złamać niezmienioną nadklasę itp.
Krótko mówiąc, masz szereg złych konsekwencji, które zwykle są wystarczająco złe, aby odrzucić takie rozwiązania z ręki. Jeśli kilka podklas robi to samo i chcesz uniknąć powielania kodu (praktycznie zawsze jest to dobra rzecz), lepszym rozwiązaniem jest wprowadzenie klasy średniej, z której wszystkie te podklasy mogą odziedziczyć kod.
źródło
Nie tylko nie powinien wiedzieć, ale po prostu nie może ! Zazwyczaj zajęcia mogą być przedłużane w dowolnym miejscu i czasie. Można go rozszerzyć o klasy, które nawet nie istniały, kiedy zostały napisane.
Niektóre języki pozwalają na kontrolowanie rozszerzania klas przez nadklasę. W Scali klasę można oznaczyć jako
sealed
, co oznacza, że można ją rozszerzyć tylko o inne klasy w tej samej jednostce kompilacji (plik źródłowy). Jednakże, chyba że te podklasy są równieżsealed
lubfinal
, podklasy można następnie rozszerzyć o inne klasy.W Scali służy do modelowania zamkniętych typów danych algebraicznych, więc kanoniczny
List
typ Haskell :można modelować w Scali w następujący sposób:
I można zagwarantować, że tylko opuszczeniu w tych dwóch podsystem „klas”, bo
List
jestsealed
i nie może być przedłużony poza pliku,Cons
jestfinal
i nie może być rozszerzony na wszystkich iNil
toobject
, które nie mogą zostać rozszerzone tak.Ale jest to szczególny przypadek użycia (modelowanie algebraicznych typów danych poprzez dziedziczenie) i nawet w tym przypadku nadklasa tak naprawdę nie wie o swoich podklasach. Jest to bardziej gwarancja dla użytkownika tego
List
typu, że jeśli podejmie dyskryminacjęNil
iCons
nie będzie żadnej innej alternatywy wyskakującej za jego plecami.źródło
abstract internal
członkowskich.Prostą odpowiedzią jest: nie.
Sprawia, że kod jest kruchy i unieważnia dwie podstawowe zasady programowania obiektowego.
źródło
Tak czasami. Na przykład, gdy istnieje ograniczona liczba podklas. Odwiedzający jest ilustracją użyteczność tego podejścia.
Przykład: abstrakcyjne węzły drzewa syntaktycznego (AST) o dobrze zdefiniowanej gramatyce mogą być dziedziczone z pojedynczej
Node
klasy implementującej wzorzec gościa do obsługi wszystkich typów węzłów.źródło
Node
Klasa podstawowa oczywiście nie zawiera żadnych bezpośrednich odniesień do jej podklas. Ale zawieraaccept
metodę zVisitor
parametrem. IVisitor
zawieravisit
metodę dla każdej podklasy. Mimo żeNode
nie ma bezpośrednich odniesień do swoich podklas, „wie” o nich pośrednio, poprzezVisitor
interfejs. Wszyscy przez to połączyli się.Jeśli piszę komponent dla firmy, a później, po odejściu, ktoś rozszerza go na własne potrzeby, czy powinienem zostać o tym poinformowany?
Nie!
To samo z klasami. Zaufaj instynktowi.
źródło