Dziedziczenie - konstruktory klasy bazowej i potomnej Drukuj
Ocena użytkowników: / 12
SłabyŚwietny 
Instrukcje dodatkowe - Programowanie w języku JAVA
Wpisany przez Administrator   

 

Z tej lekcji nauczysz się:

  • jakie typy konstruktorów możemy stosować w zestawieniu z dziedziczeniem:
    • konstruktor bezparametrowy
    • konstruktor, który przyjmuje jeden lub więcej parametrów typu prostego(double, int, char itd.)
    • konstruktor, który przyjmuje jako parametr obiekt złożonego typu
  • kiedy przydaje się konkretny typ konstruktora

 

Na początek zadanie przypominające:

Zad. 1. Napisz program, który:

  • definiuje klasę kwadrat zawierającą:
    • pole bokA;
    • metodę ustaw_a, która zmienia wartość pole bokA;
    • konstruktor;
  • definiuje klasę prostokąt, która dziedziczy z klasy kwadrat, oprócz tego:
    • zawiera dodatkowe pole bokB;
    • zawiera dodatkową metodę ustaw_b, która zmienia wartość pola bokB;
    • zawiera dodatkową metodę ustaw_a_b, która zmienia wartość pól bokA oraz bokB i korzysta z gotowych metod ustaw_a oraz ustaw_b;
    • zawiera konstruktor;

Spróbuj sam napisać ten program, na końcu instrukcji znajduje się rozwiązanie dla porównania.

 


 

Czym jest konstruktor? (przykład konstruktora bezparametrowego)

Przypomnijmy to, co było na poprzedniej instrukcji, że konstruktor jest metodą, która tworzy nowy obiekt danej klasy. Domyślnie (jeśli nie zdefiniujemy inaczej), dla każdego pola klasy przy tworzeniu nowego obiektu ustawiane są wartości domyślne dla każdego z tych pól. Dzieje się tak w tzw.: konstruktorach bezparametrowych (w naszym przykładzie dla klasy kwadrat konstruktor bezparamatrowy wygląda tak:

kwadrat(){}

a dla klasy prostokat tak:

prostokat(){}

Sprawdźmy, czy tak rzeczywiście jest. Do naszej klasy kwadrat dodajmy metodę wyświetlającą wartość boku a:

Zad. 2 Zmodyfikuj powyższy program tak, aby klasy zawierały metody wyświetlające wartości poszczególnych pól.

Spróbuj sam napisać ten program, na końcu instrukcji znajduje się rozwiązanie dla porównania.

 

Teraz sprawdźmy, czy rzeczywiście jest tak, jak mówi teoria. Sprawdzimy to na przykładzie:

Zad. 3: Zmodyfikuj powyższy program tak, aby wywołać obiekt klasy kwadrat o nazwie kw1 za pomocą konstruktora bezparametrowego. Używając odpowiedniej metody wyświetl wartość pola bokB.

W linijce 37 został utworzony obiekt o klasy kwadrat, który nazywa się kw1. Jego utworzeniem "zajął się" bezparametrowy konstruktor (new kwadrat();) (zauważ, że w nawiasach nie ma parametrów).

W linijce 38 wywołano procedurę wyświetlającą wartość pola bokB;

Oto wynik wywołania tej procedury:

Wniosek: tak, jak napisano wcześniej, bezparametrowy konstruktor tworzy nowy obiekt danej klasy, przy czym poszczególne pola przyjmują wartość domyślną dla danego typu, u nas jest to 0,0 dla typu double.

 


Konstruktor z jednym lub większą ilością parametrów

 

Często jednak potrzebujemy tworzyć nowe obiekty danej klasy i to w taki sposób, aby "już na starcie" wartości tych pól były zdefiniowane. W tym używamy konstruktorów przyjmujących pewne parametry, które przydają się w ustawieniu wartości pól nowego obiektu. Pokażmy to na przykłądzie:

Zad. 4: Zmodyfikuj powyższy program tak, aby:

  • tworzył nowy obiekt klasy prostokat o wartościach pól: bokA = 45, bokB=45,6.
  • za pomocą odpowiedniej metody wyświetlał wartości pól bokA oraz bokB;

Podpowiedź: dla lepszej "czytelności" kodu lepiej jest usunąć linijki wpisane w  zadaniu 3.

Oto, jak wygląda kod do zadania:

Oto efekt działania programu:

Czyli konstruktor faktycznie stworzył nowy obiekt o zadanych wartościach pól.

 

 


 

Konstruktory przyjmujące obiekt jako parametr

Ostatnim typem konstruktorów jest taki, który jako argument (parametr) przyjmuje obiekt danego typu i na podstawie "wyciągniętych z niego danych" tworzy nowy obiekt i ustawia wartości jego pól. Zobaczmy to na przykładzie:

Zad. 5: Zmodyfikuj powyższy program tak, aby:

  • tworzył nowy obiekt klasy kwadrat o nazwie kw2 i wartości pola bokA = 50;
  • tworzył nowy obiekt klasy prostokat o nazwie pr2 i wartości pola bokB = 100;
  • wywołując odpowiednią metodę wyświetlał wartość tych pól

Podpowiedź: dla lepszej "czytelności" kodu lepiej jest usunąć linijki wpisane w  zadaniu 4.

Oto, jak wygląda kod do zadania:

 

Oto efekt działania programu:

 

Oczywiście wartość pola bokB została ustawiona na domyślną, czyli 0,0 dla typu long.

Ważne jest jednak to, że konstruktor dobrze wywiązał się ze swojego działania i stworzył obiekt pr2 na podstawie obiektu kw2.

 

 


 

Dziedziczenie konstruktorów

Aby zrozumieć, czym jest dziedziczenie konstruktorów posłużmy się następującym scenariuszem:

 

Zad. 6: Zmodyfikuj powyższy program tak, aby:

a) konstruktor domyślny dla klasy kwadrat ustalał wartość pola bokA na 10.

b) wywołanie odpowiedniej metody wyświetlenie wartości tego pola

 

Oto, jak wygląda kod do zadania:

Teraz wywołajmy metodę, która wyświetli wartość pola bokA:

 

Jak widać, konstruktor domyślny ustalił wartość pola bokA na 10.

Teraz sprawdźmy, czy konstruktory też są dziedziczone przez klasy potomne. Jak pamiętamy, klasa prostokat dziedziczy z klasy kwadrat, więc teoretycznie konstruktor domyślny klasy prostokat też dziedziczy z konstruktora kwadrat. Innymi słowy, w skład konstruktora domyślnego klasy prostokat wchodzi konstruktor domyślny klasy kwadrat.

Aby to sprawdzić, wywołajmy konstruktor domyślny klasy prostokat dla obiektu, tej klasy. Jeśli mamy rację, to utworzenie obiektu tej klasy za pomocą konstruktora domyślnego sprawi, że wartość pola bokA będzie wynosiła 10, natomiast wartość pola bokB będzie domyślna i wyniesie 0.

Zad. 7: Zmodyfikuj powyższy program tak, aby:

a) stworzyć obiekt klasy prostokat

Czyli konstruktor domyślny też jest dziedziczony, tak, jak każdy inny konstruktor.

 

 


 

Modyfikowanie dziedziczonego konstruktora

 

Załóżmy, że chcemy, aby nasz konstruktor domyślny w klasie prostokat, który jest dziedziczony z klasy kwadrat można było zmodyfikować tak, aby również ustalać wartość pola bokB na 20.

Zad. 8: Zmodyfikuj powyższy program tak, aby konstruktor domyślny klasy prostokat ustalał wartość pola bokB na 20.

 

i wywołanie (sprawdzamy, czy działa):

Czyli wszystko działa jak należy: wartość pola bokA została ustalona dzięki dziedziczonemu konstruktorowi kwadrat(), natomiast wartość pola bokB została ustawiona na 20 dzięki zastosowaniu polecenia super();, które jest dla kompilatora informacją, że po niej nastąpią dodatkowe instrukcje, obok tych dziedziczonych.

 

 


 

Zadania do samodzielnego wykonania

Zad. 9: Napisz program który:

  • definiuje klasę punktGPS, która zawiera:
    • pole wspx, wspy;
    • konstruktor bezparametrowy;
    • konstruktor, który narzuca wspx = 43, wspy = 56;
    • metody potrzebne do wprowadzenia oraz wyświetlenia wartości poszczególnych pól;
  • definiuje klasę punkGPS_z_wys, która:
    • dziedziczy z klasy punktGPS;
    • zawiera pole wysokosc;
    • konstruktory dziedziczą z konstruktorów klasy punktGPS (gdzie się tylko da wykorzystujemy polecenie super() do uzupełnienia konstruktorów;

 


 

Rozwiązania zadań:

Zadanie 1:

Zad. 2:

Dziękuję za uwagę.