Modyfikacja konstruktora w podklasie

0

Cześć, mam kilka pytań, będę wdzięczny za pomoc

Mam 3 klasy (usunąłem nieistotne dla postu metody i zmienne)

abstract class Employee {

	private String name;				//
	private double baseSalary;			//

	public Employee(String name, double baseSalary) {
		this.name = name;				// 
		this.baseSalary = baseSalary;	// 
	}

  	public double getBaseSalary() {
		return baseSalary;				//
  	}

}

abstract class TechnicalEmployee extends Employee {
	public TechnicalEmployee(String name) {
		super(name, 75000);			//
	}
}

class TechnicalLead extends TechnicalEmployee {
	public TechnicalLead(String name) {
		???????						//
	}
}

Linie bez znaku komentarza nie mogą być zmienione (poza modyfikatorami klas), muszę użyć tych klas i metod, bez zmiany ich parametrów.

Moje pytania:

  1. Zakładam, że dobrze zrobiłem nadając klasy abstrakcyjne, jeśli instancjami będą jedynie TechnicalLead?
  2. Zakładam też, zmienne w Employee powinny być private?
  3. TechnicalEmployee musi mieć baseSalary 75000. Zakładam, że mój konstruktor jest ok?
  4. TechnicalLead musi mieć 1.3 * baseSalary TechnicalEmployee. Tu mam problem, nie wiem jak to ugryźć.
1

Wszystkie Twoje założenia są dobre.

Ja zakładamy że technical lead musi dziedziczyć z technical employee?

Bo jeśli tak, to w Twoim przykładzie technical employee (czyli również technical lead) musi mieć salary jednocześnie 7300 oraz 7300*1.3. Co jest oczywiście nie możliwe. Bo patrz, mówisz że technical employee ma mieć 7300, a technical lead który jest technical employee (więc ma 7300) ma mieć więcej.

Rozumiem, że to znaczy że każdy technical employee który nie jest technical leadem ma mieć 7300? W takim wypadku to nie technical employee powinien ustawiać cenę w konstruktorze, tylko klasy wyżej (np tech lead, albo inne dziedziczące z tech employee).

0

Jaki jest kontekst problemu?

Dostarczenie przykładu z dziedziczeniem na jakieś zajęcia? Czy może realny problem do rozwiązania?

1

W skrócie, jeśli ma to być parametr konstruktora - to w technical employee musi być przynajmniej jeden konstruktor który ma sallary jako parametr.
Jeśli nie musi to być parametr konstruktora, to możesz zrobić metodę abstrakcyjną getBaseSallary() którą różne klasy będą implementowały w różny sposób.

4

Mkbewe już wysłany za to private double baseSalary;

MKbewe

0

Układ klas powinien wyglądać tak:

				 				          Employee

                TechnicalEmployee                                    BusinessEmployee
                baseSalary 75000                                     baseSalary 50000

SoftwareEngineer          TechnicalLead			         BusinessLead		       Accountant
                          1.3 * TechnicalLead        
                          baseSalary                     

Parametry konstruktorów z pierwszego posta nie mogą być zmienione.
Pod nazwami klas umieściłem wymogi dla baseSalary poszczególnych klas.
Nie jest możliwe aby konstruktor TechnicalLead nadpisał konstruktor TechnicalEmployee zwiększając baseSalary?

1
MichałL napisał(a):

Nie jest możliwe aby konstruktor TechnicalLead nadpisał konstruktor TechnicalEmployee zwiększając baseSalary?

Nope. I bardzo dobrze, bo nie miałoby to sensu.

2
MichałL napisał(a):

Układ klas powinien wyglądać tak:

  			 				          Employee

                TechnicalEmployee                                    BusinessEmployee
                baseSalary 75000                                     baseSalary 50000

SoftwareEngineer TechnicalLead BusinessLead Accountant
1.3 * TechnicalLead
baseSalary

Ok, kluczowe pytanie - czy rozumiesz, że to nie jest tak że TechnicalLead jest jakoś pod/nad TechnicalEmployee? To znaczy że TechnicalLead jest TechnicalEmployee.
Ten diagram który wkleiłeś wyżej, sugeruje że TechnicalLead ma mieć baseSalary = 75000 oraz baseSalary = 1*3 baseSalary (dwie definicje). Więc w taki sposób na pewno nie da się tego zrobić (trochę jakbyś chciał powiedzieć "jestem 1.3 razy starszy od samego siebie".

Parametry konstruktorów z pierwszego posta nie mogą być zmienione.
Pod nazwami klas umieściłem wymogi dla baseSalary poszczególnych klas.

No to masz jeszcze do wyboru dodać drugie pole salary. Wtedy będziesz miał dwa pola baseSalary oraz salary. I baseSalary = 73000 a salary = baseSalary * 1.3. Tylko to ma taką wadę że żadna logika w Employee albo TechnicalEmployee nie będzie o tym wiedzieć.

Drugie wyjście to nadpisanie metody getBaseSalary(). Ma to sens tylko wtedy jeśli żadne funkcje nie operują na polu baseSalary, a wszystkie korzystają z tego gettera.

Trzecim, najlepszym byłaby edycja konstruktora - ale z jakiegoś tajemniczego powodu, nie można go użyć.

0

To jest projekt z kursu Javy na edX. Nie jest powiedziane, że ustawienia baseSalary w podklasach mają być z poziomu konstruktorów. Wydaje mi się, że faktycznie nadpisanie getBaseSalary() w podklasach jest dobrym rozwiązaniem.

Parametry konstruktorów oraz nazwy i parametry metod są podane w treści projektu, dlatego nie mogę ich zmienić. Od siebie mogę umieścić zmienne w miejscach, które uważam za ok oraz nadpisać konstruktory lub metody.

1
MichałL napisał(a):

Od siebie mogę umieścić zmienne w miejscach, które uważam za ok oraz nadpisać konstruktory lub metody.

Nie ma czegoś takiego jak nadpisanie konstruktora.

Najwyżej możesz użyć konstruktora super-klasy w pod-klasie.

0

Ok. Postaram się oprzeć wszystko o getBaseSalary(). Dzięki za pomoc.

Diagram jest przeklejony z projektu. Założenia co do baseSalary z opisu klas.

Co jest nie tak z private double baseSalary ?

0

Java to nie moja dziedzina, ale czemu nikt mu nie pisze o interface'ach?
Z tego co wiem to użycie interface'ów jest bardziej elastyczne inż zwykłe dziedziczenie.

4
MichałL napisał(a):

Co jest nie tak z private double baseSalary ?

Nie trzyma się pieniędzy w liczbach zmiennoprzecinkowych

0
Kamil Żabiński napisał(a):
MichałL napisał(a):

Co jest nie tak z private double baseSalary ?

Nie trzyma się pieniędzy w liczbach zmiennoprzecinkowych

niestety getBaseSalary() ma zwracać double, ale wiem, że przy operacjach na tym typie występują błędy

2
MichałL napisał(a):

niestety getBaseSalary() ma zwracać double, ale wiem, że przy operacjach na tym typie występują błędy

To że getBaseSalary() ma zwracać double, nie znaczy że pole baseSalary ma je przechowywać jako double. Mogłoby np być

int baseSalary = 120; // 120 groszy

double getBaseSalary() {
  return baseSalary / 100.0;
}

Ale skoro chcesz oprzeć wszystko na tym getterze, to taka zamiana i tak nic nie da.


Powiem wprost, żebyś wiedział. Te założenia, które są Ci narzucane - są bez sensu. Robienie tak aplikacji, moim zdaniem, to uczenie się złych nawyków. Nie robiłbym tego, chyba że nie miałbym innego wyjścia.

0
TomRiddle napisał(a):

Powiem wprost, żebyś wiedział. Te założenia, które są Ci narzucane - są bez sensu. Robienie tak aplikacji, moim zdaniem, to uczenie się złych nawyków. Nie robiłbym tego, chyba że nie miałbym innego wyjścia.

Dzięki za sugestię i za pomoc, ten już chyba skończę, ale poważnie rozważę ciągnięcie tego dalej.

0

Przejrzałem GitHuba i z tego co widzę są stosowane głównie 2 rozwiązania.

Zmienne w Employee jako public, ale rozumiem, że to nie jest dobre rozwiązanie.

Dodatkowy konstruktor w TechnicalEmployee mający za parametry String name i double multiplier. W TechnicalLead jest zmienna multiplier równa 1.3 podawana jako argument przy wywoływaniu konstruktora TechnicalEmployee.

2
MichałL napisał(a):

Przejrzałem GitHuba i z tego co widzę są stosowane głównie 2 rozwiązania.

Zmienne w Employee jako public, ale rozumiem, że to nie jest dobre rozwiązanie.

public final BigDecimal kosztZupy;

jest o kilka klas lepszy
niż

private  BigDecimal kosztZupy;

public void setKosztZupy(BigDecimal kosztZupy) {
    kosztZupy = kosztZupy;
}
0
jarekr000000 napisał(a):

public final BigDecimal kosztZupy;

jest o kilka klas  lepszy 
niż 

private BigDecimal kosztZupy;

public void setKosztZupy(BigDecimal kosztZupy) {
kosztZupy = kosztZupy;
}

W rozwiązaniach, na które parzyłem nie było final, ale biorąc pod uwagę, że w zadaniu i tak nie ma metody setBaseSalary() to chyba faktycznie jest dobra opcja. Chyba, że jest coś o czym nie wiem?

0

Nie wnikałem w meandry waszych rozważań o dziedziczeniu ale widzę podstawowy problem w twoim kodzie.

Nie przejmuj się bo wiele doświadczonych osób o tym też nie wie. Otóż chodzi mi o reprezentację wartości pieniężnych za pomocą doubla co jest błędne. Więcej możesz poczytać tutaj https://stackoverflow.com/q/179427/2401535.

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