Dziedziczenie klas

0

Cześć. Jestem bardzo początkujący i mam taki problem:

mam klasę Pracownik i chcę wpisać takie argumenty, by każdy Pracownik był albo pracownikiem fizycznym albo pracownikiem umysłowym. Jak to zrobić? Jakieś pomysły. Będę wdzięczny za odpowiedź.

1

Zrób sobie jakiś enum w którym zdefiniujesz 2 stałe.
Następnie w klasie pracownik dodaj to pole.

0

Albo zrób zmienna boolean która będzie definiowała typ pracownika.

2

Masz dwie drogi. Pierwsza oparta o enumy, która jest prosta i przyjemna, ale działa tylko wtedy, gdy flagę taką wykorzystujesz jedynie do generowania klasy css. Zazwyczaj kończy się, to kodem w rodzaju:

if(pracownik.isFizyczny()){
	//...
} else if(pracownik.isUmysłowy()){
	//...
} else{}

w dodatku taki kod rozprzestrzenia się po całym projekcie.

Dlatego jeżeli z tymi typami pracowników jest powiązana jakaś logika, to należy klasycznie dziedziczeniem:

class Pracownik{}

class PracownikFizyczny extends Pracownik{}
class PracownikUmysłowy extends Pracownik{}

Potem w kodzie zamiast if-ów masz metody przyjmujące różne typy i niech kompilator martwi się, co tam dokładnie pod spodem należy wykonać.

0
lukasz1988 napisał(a):

Albo zrób zmienna boolean która będzie definiowała typ pracownika.

Dla ludzi z takimi pomysłami jest specjalne miejsce w piekle! ;>

0
Koziołek napisał(a):

Masz dwie drogi. Pierwsza oparta o enumy, która jest prosta i przyjemna, ale działa tylko wtedy, gdy flagę taką wykorzystujesz jedynie do generowania klasy css. Zazwyczaj kończy się, to kodem w rodzaju:

if(pracownik.isFizyczny()){
	//...
} else if(pracownik.isUmysłowy()){
	//...
} else{}

w dodatku taki kod rozprzestrzenia się po całym projekcie.

Dlatego jeżeli z tymi typami pracowników jest powiązana jakaś logika, to należy klasycznie dziedziczeniem:

class Pracownik{}

class PracownikFizyczny extends Pracownik{}
class PracownikUmysłowy extends Pracownik{}

Potem w kodzie zamiast if-ów masz metody przyjmujące różne typy i niech kompilator martwi się, co tam dokładnie pod spodem należy wykonać.

Dróg jest więcej niż dwie.

Zgadzam się, że Twoja druga propozycja lepsze rozwiązanie niż pierwsza, ale co w momencie, gdy poza podziałem na pracowników fizycznych i umysłowych dojdzie jeszcze inny, np. na menadżerów i podwładnych, stałych i kontraktowych, etc.?

Tego już nie da się wcisnąć w drzewiastą hierarchię dziedziczenia, więc zostaniemy z tym, że jeden podział "żyje" w formie hierarchii klas, a pozostałe i tak zmuszeni jesteśmy obsługiwać flagami, czy jakąś inną alternatywą. I zawsze będzie to nieco dezorientujące.

Z tego względu najbardziej godnym polecenia rozwiązaniem jest chyba w ogóle zastąpienie dziedziczenia kompozycją / delegacją, np. z użyciem wzorca dekorator. Dla początkujących: https://en.wikipedia.org/wiki/Decorator_pattern#Java

Muszę przyznać że ja jestem coraz bardziej krytyczny jestem wobec dziedziczenia i traktuję je jako zło konieczne.

0

Akurat dekorator jest słabym rozwiązaniem jeżeli chcesz dodawać nowe funkcjonalności. Klasa Manager prawie na pewno będzie posiadała nowe metody i pola. Zatem nie opędzisz tego dekoratorem, ponieważ ten nie może modyfikować API. Jednak dobrze, że wspomniałeś o tym wzorcu, bo należy pamiętać, iż dziedziczenie oznacza dodawanie funkcjonalności, a nie tylko modyfikację istniejących. W przypadku modyfikacji dekorator będzie OK.

0

No oczywiście masz rację, ale jeśli jest potrzebne dodanie nowych metod, to i tak zawsze można stworzyć osobną klasę (Manager), która jednak nie będzie dziedziczyć z Employee, ale wspierać jego interfejs i wywołania "starych" metod delegować, po drodze robiąc jakieś fikuśności. To wciąż podejście elastyczniejsze, niż zwyczajne dziedziczenie.

Jak to mówią, your mileage may vary i zależnie od szczegółów implementacji mogą przeważyć zalety takiego czy innego podejścia. Warto - jak mi się zdaje - po prostu pamiętać, że i takie rozwiązanie mamy w swej dyspozycji. A moja ogólna "reguła kciuka" jest taka, żeby nie sięgać po dziedziczenie odruchowo, jako pierwszą dostępną opcję, tylko po odrzuceniu innych sposobów.

Bo chociaż tutoriale ćwiczą początkujących programistów w tym, by sięgali po nie lekką ręką, na dłuższą metę ma ono swój koszt. Po jakimś czasie może się nam zrobić trudna w refaktoryzacji struktura, niełatwy debugging (skakanie w głąb i do góry po hierarchii), problemy typu fragile base class. Trochę przekonali mnie do tego sceptycyzmu adwokaci programowania funkcyjnego.

1 użytkowników online, w tym zalogowanych: 0, gości: 1