programowanie w środowisku graficznym- wykład 2

40
Java - Klasy Treści prezentowane w wykładzie zostały oparte o: Barteczko, JAVA Programowanie praktyczne od podstaw, PWN, 2014 http://docs.oracle.com/javase/8/docs/ C. S. Horstmann, G. Cornell, Java. Podstawy, Helion, Gliwice 2013 Programowanie w środowisku graficznym- wykład 2

Upload: others

Post on 16-Oct-2021

6 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Programowanie w środowisku graficznym- wykład 2

Java - Klasy

Treści prezentowane w wykładzie zostały oparte o:

● Barteczko, JAVA Programowanie praktyczne od podstaw, PWN, 2014

● http://docs.oracle.com/javase/8/docs/

● C. S. Horstmann, G. Cornell, Java. Podstawy, Helion, Gliwice 2013

Programowanie w środowisku graficznym- wykład 2

Page 2: Programowanie w środowisku graficznym- wykład 2

21.02.2018 2

1. Klasy i obiekty w JavieDefiniowanie klasy jest równoznaczne z tworzeniem wzorca (przepisu) danego obiektu, który umożliwia tworzenie obiektów tej klasy.

[atrybutyDostepu] class NazwaKlasy [extends NazwaNadklasy] [implements NazwyInterfejsów]{

//ciało klasy tj.

//definicje składowych klasy:

//pól, konstruktorów, metod, bloków inicjujących

}

Wyróżnia się cztery atrybuty dostępu:

● public (publiczny)-możliwość dostępu z dowolnej klasy

● protected (chroniony)-możliwość dostępu z każdej klasy pochodnej lub klas należących do tego samego pakietu

● private (prywatny)-możliwość dostępu wyłącznie w danej klasie

● dostęp domyślny (bez podanego specyfikatora dostępu) - możliwość dostępu wyłącznie z klas należących do tego samego pakietu

Page 3: Programowanie w środowisku graficznym- wykład 2

21.02.2018 3

POLA● UWAGA: w pliku źródłowym może występować tylko jedna klasa

publiczna i jeśli występuje, to plik musi mieć taką samą nazwę jak ta klasa, z uwzględnieniem wielkości liter.

● W ciele klasy definiowane są składniki klasy, tj. zmienne (pola) i metody. Pola określają z jakich elementów składają się poszczególne obiekty klasy, zaś metody określają działania, które można na nich wykonywać.

● DEFINIOWANIE PÓL KLASY

[specyfikator_dostępu][static] nazwa_typu nazwa_pola [inicjator];

● Przykład

public class Para {

private int a;

private int b; // = 6;

//...

}

Page 4: Programowanie w środowisku graficznym- wykład 2

21.02.2018 4

METODY

● Przy tworzeniu obiektów pola klasy zawsze uzyskują początkowe, domyślne wartości (zerowe)

● DEFINIOWANIE METOD KLASY

[public ]class NazwaKlasy{

//...

[specyfikator_dostępu][static] typ_wyniku

nazwa_metody(lista parametrów){

//ciało metody tj.

//instrukcje wykonywane po wywołaniu metody

}

}

Page 5: Programowanie w środowisku graficznym- wykład 2

21.02.2018 5

METODY

● Lista parametrów zawiera rozdzielone przecinkami deklaracje parametrów, które metoda otrzymuje przy wywołaniu.

● Jeśli metoda zwraca wynik, to w definicji określamy konkretny typ_wyniku i zakończenie jej działania powinno nastąpić na skutek instrukcji return [wyrażenie];zwracającej dane typu_wyniku, jeśli nie zwraca żadnego wyniku, to jej typ_wyniku określamy słowem kluczowym void (zakończenie metody następuje po dotarciu do ostatniego nawiasu „}” lub” instrukcji return;).

● W Javie argumenty przekazywane są metodom wyłącznie przez wartość, tj. w metodzie odwołujemy się do kopii argumentu.

● Metody statyczne (static) nie są wywoływane na rzecz obiektów, mogą zatem być wywoływane nawet, gdy nie istnieje żaden obiekt danej klasy.

Page 6: Programowanie w środowisku graficznym- wykład 2

21.02.2018 6

KONSTRUKTORY● Konstruktor służy głównie do inicjowania wartości pól obiektów.

Konstruktor ma nazwę jak nazwa klasy i nie ma żadnego typu wyniku.

● DEFINIOWANIE KONSTRUKTORÓW

[public ]class NazwaKlasy{

[specyfikator_dostępu]

nazwa_klasy(lista_parametrów){

//czynności wykonywane przez konstruktor

}

}

● Konstruktory zawsze są wywoływane za pomocą wyrażenia new : NazwaKlasy tworzonyObiekt = new NazwaKlasy(parametryKonstruktora)

● Jeśli w klasie nie zdefiniowano żadnego konstruktora, to do definicji klasy automatycznie dodawany jest konstruktor bezparametrowy (który nie robi nic).

Page 7: Programowanie w środowisku graficznym- wykład 2

21.02.2018 7

KONSTRUKTORY c.d.

● PRZYKŁAD

public class Para{

private int a, b; //pola klasy

public Para(int x, int y){

a=x;b=y;//nadaje polom a i b, wartości

//przekazane jako argumenty konstruktora

}

public Para(int x){

a=x; b=x;//nadaje obu polom wartość x

}

}

Dla tak zdefiniowanej klasy, możemy tworzyć obiekty:

Para p1 = new Para(10,7); // para 10 7

Para p2 = new Para(5); //para 5 5

Page 8: Programowanie w środowisku graficznym- wykład 2

21.02.2018 8

SKŁADOWE STATYCZNE

● Składowe (pola i metody) niestatyczne (instancyjne) zawsze wiążą się z istnieniem obiektu danej klasy

● Składowe statyczne (klasowe) tzn. ze specyfikatorem static

nie dotyczą obiektów, ale całej klasy – są wspólne dla wszystkich obiektów tej klasy

mogą być używane nawet wtedy, gdy nie istnieje żaden obiekt klasy

do składowych statycznych odwołujemy się NazwaKlasy.nazwaSkładowej

UWAGI:

● Pola niestatyczne (instancyjne) istnieją w każdym obiekcie klasy, natomiast dla pól statycznych (klasowych) przydzielany jest tylko jeden obszar pamięci na całą klasę

● Z metod statycznych nie wolno odwoływać się do niestatycznych składowych klasy (gdyż obiekt może nie istnieć)

PRZYKŁADY

● metoda main – musi być statyczna ponieważ od niej zaczyna się wykonywanie programu, a w tym momencie nie istnieje jeszcze żaden obiekt.

Page 9: Programowanie w środowisku graficznym- wykład 2

21.02.2018 9

SKŁADOWE STATYCZNE c.d.

● W klasie System (dostarczanej jako klasa standardowa) jest stała statyczna out (obiekt klasy PrintStream oznaczający standardowe wyjście)public class System{ . . .

public final static PrintStream out; . . .

}W klasie PrintStream (jedna z klas standardowych) zdefiniowane są metody println, wypisujące do strumienia wyjściowego -PrintStream podane argumentypublic class PrintStream{ . . .

public void println(String s){...}}Zatem

● System.out to statyczne pole klasy System● println to metoda używana na rzecz tego obiektu

Stąd: System.out.println(String s)

Page 10: Programowanie w środowisku graficznym- wykład 2

21.02.2018 10

PRZECIĄŻANIE KONSTRUKTORÓW

● Analogicznie możemy przeciążać konstruktory, czyli w jednej klasie możemy mieć konstruktory z różnymi parametrami.

● Aby nie powtarzać wspólnego kodu w różnych konstruktorach wygodnie jest wywoływać konstruktor w innym konstruktorze. Do takich wywołań używamy słowa kluczowego this().

● PRZYKŁAD

public class Para{

private int a,b;

public Para(){}//konstruktor bezparametrowy

public Para(int x, int y){a=x; b=y;}

public Para(int x){

this(x,x);

}

}//this(...) musi być 1 instrukcją w ciele konstruktora

Page 11: Programowanie w środowisku graficznym- wykład 2

21.02.2018 11

OBIEKTY I REFERENCJE

public class Para{

private int a,b;

public Para(){}//konstruktor bezparametrowy

public Para(int x, int y){

a = x; b = y;

}

//metoda ustalająca składniki pary

public void set(int x, int y){

a = x; b = y;

}

//metoda pokazująca parę

public void show(){

System.out.println(”(” + a + ”,” + b + ”)”);

} }

Page 12: Programowanie w środowisku graficznym- wykład 2

21.02.2018 12

PRZECIĄŻANIE METOD● Przeciążanie metod i konstruktorów polega na definiowaniu metod o

tej samej nazwie, ale różniących się liczbą i/lub typami argumentów np. metoda println() ma bardzo wiele wersji z argumentami różnych typów.

● PRZYKŁAD dla klasy Para o prywatnych polach int a,b

void add(Para p)//dodaje do pary, na rzecz

//której wywołano metodę, parę p

void add(int i)//do obu pól pary dodaje podaną liczbę

void add(int x, int y)//pierwszy argument dodaje do

//1-go skł. Pary, a 2-gi do 2-go

● UWAGA: Należy specyfikować parametry o radykalnie różnych typach (aby uniknąć pomyłek wynikających z automatycznej konwersji typów) np. dla dwóch metod o tej samej nazwie z parametrami int i short, próba wywołania metody z parametrem char spowoduje wywołanie metody z parametrem int

● Nie istnieje możliwość deklarowania metod o tej samej nazwie, sygnaturze, ale o rożnym typie wyniku.

Page 13: Programowanie w środowisku graficznym- wykład 2

21.02.2018 13

OBIEKTY I REFERENCJE

● Fragment funkcji main() z klasy TestPary:

Para p = new Para();//wywołanie konstruktora bezparametrowego

p.set(1,2);

p.show();

● Obiekt musi być utworzony za pomocą wyrażenia new (Sama deklaracja np. Para p; nie wystarcza). Dopiero zastosowanie wyrażenia new powoduje przydzielenie pamięci dla obiektu (na stercie). Wynikiem tego wyrażenia jest adres miejsca w pamięci przydzielonego obiektowi – referencja. Zatem zmienna p z przykładu zawiera referencję do obiektu klasy Para.

● Wszystkie zmienne deklarowane z nazwą klasy w miejscu nazwy typu są zmiennymi typu referencyjnego (zawierają referencje do obiektów lub null).

Page 14: Programowanie w środowisku graficznym- wykład 2

21.02.2018 14

OBIEKTY I REFERENCJE

● Dla zmiennych typów referencyjnych możemy:

– Porównywać referencję ( == lub !=)

– Przypisywać im wartości innych referencji oraz null

● Operacje wykonywane na zmiennych obiektowych dotyczą referencji, a nie obiektów (operacje arytmetyczne są niedozwolone). Na obiektach (ich wnętrzu) operujemy za pomocą metod zdefiniowanych w klasie obiektu.

● PRZYKŁAD

Para p=new Para(1,2);//tworzony jest obiekt,wywoływany

//jest dla niego konstruktor,nadający wartości polom,

//new zwraca referencję do obiektu i podstawia pod p

Para p1=new Para();//nowy obiekt o wartościach 0,0

p1=p;//kopiujemy referencję, teraz oba obiekty

//wskazują na to samo miejsce w pamięci

p1.show(); //(1,2)

Page 15: Programowanie w środowisku graficznym- wykład 2

21.02.2018 15

SŁOWO KLUCZOWE this● Wyrażenie new tworzy obiekt (przydziela pamięć i inicjuje wartości zerami), a

następnie dla nowo utworzonego obiektu uruchamiany jest konstruktor.● W konstruktorze dostępna jest referencja do tego obiektu w postaci niejawnie

zdefiniowanej zmiennej this.● this używamy przy przesłonięciu nazw zmiennych oznaczających pola.

public class Para{

private int a,b;

public Para(){

this(0,0);//this() -pierwsza instrukcja konstruktora //pozwala wywołać w nim inny konstruktor }

public Para(int a, int b){ this.a = a; this.b = b; } //this.a, this.b pola obiektu inicjowanego //przez konstruktor //lub na rzecz którego wywołano metodę

Page 16: Programowanie w środowisku graficznym- wykład 2

21.02.2018 16

SŁOWO KLUCZOWE this● Ponieważ obiekt na rzecz którego wywołano metodę, jest wewnątrz

metody reprezentowany przez this, dlatego kolejnym przypadkiem jego użycia są metody zwracające referencję do obiektu na rzecz którego zostały wywołane, np. metoda dodająca parę przekazaną jako argument do pary, na rzecz której wywołano metodę i zwracająca otrzymany wynik:

Para add(Para p){

a += p.a; b += p.b;

return this;}

Przykładowe wykorzystanie powyższej metody (kaskadowe):

Para suma = new Para(0,0);

Para p1 = new Para(1,2);

Para p2 = new Para(3,4);

suma.add(p1).add(p2);

● this(...) używane jako pierwsza instrukcja konstruktora pozwala wywołać w nim inny konstruktor

Page 17: Programowanie w środowisku graficznym- wykład 2

21.02.2018 17

ZASIĘG ZMIENNYCH

● W każdej metodzie/konstruktorze klasy możemy odwołać się do identyfikatorów składowych klasy(pól i metod) niezależnie od tego w którym miejscu klasy są zadeklarowane.

● Zmienne zadeklarowane w metodzie/konstruktorze czyli tzw. zmienne lokalne mają zasięg lokalny- od miejsca deklaracji do końca metody, dotyczy to również parametrów deklarowanych w nagłówku metody. Próba odczytu niezainicjowanych zmiennych lokalnych powoduje błąd kompilacji.

● Zmienne deklarowane wewnątrz bloków lokalnych (zestaw instrukcji ujęty w {}) mają zasięg od miejsca deklaracji do końca bloku. Wartości zmiennych lokalnych są tracone po wyjściu sterowania z bloku (automatyczne zwolnienie pamięci).

● Java sama dba o to, aby usunąć obiekt, gdy nie istnieje już żaden wskaźnik do niego (referencja). Zajmuje się tym tak zwany garbage collector. Jeżeli w klasie zostanie zadeklarowana metoda finalize(), to będzie ona wywoływana przed zwolnieniem pamięci przydzielonej obiektowi tej klasy.

Page 18: Programowanie w środowisku graficznym- wykład 2

21.02.2018 18

PAKIETY

● Pakiety (ang.packages) są zbiorami klas służącymi ich logicznej organizacji.Pakiet grupuje klasy o wspólnej funkcjonalności.

● Standardowa biblioteka Javy składa się z wielu pakietów, do których należą java.lang, java.util, java.net. Mają one strukturę hierarchiczną. Pakiety mogą zawierać klasy, a także inne pakiety, podobnie jak w przypadku katalogów i podkatalogów. Wszystkie standardowe pakiety Javy znajdują się w pakietach java i javax.

● Pakiety chronią nas przed kolizjami nazw. Może istnieć wiele klas o takich samych nazwach w różnych pakietach np. File, dlatego używamy nazw kwalifikowanych: nazwa_pakietu.nazwa_klasy np.java.io.File f= new java.io.File(”plik.txt”);

● Każda klasa należy do jakiegoś pakietu. Dla klas definiowanych w naszych przykładach używany był pakiet domyślny (zwykle bieżący katalog).

Page 19: Programowanie w środowisku graficznym- wykład 2

21.02.2018 19

PAKIETY c.d.● Aby zachować unikalność nazw pakietów zaleca się stosowanie

w tych nazwach odwróconych domen internetowych(które są unikatowe)

● Klasy są przechowywane w podkatalogach systemu plików. Ścieżka do klasy musi odpowiadać nazwie jej pakietu. Nazwy pakietów zwyczajowo pisze się małymi literami. Kolejne poziomy zagnieżdżenia w hierarchii pakietów oddziela się od siebie kropkami, podobnie do tego jak nazwy kolejnych katalogów w ścieżce dostępu oddziela się od siebie ukośnikami.

● Jeśli zatem deklarujemy, że klasa należy do pewnego pakietu, to plik zawierający implementację tej klasy musi znajdować się w katalogu odpowiadającym temu pakietowi.

● Przykładowo, jeśli plik zawierający definicję klasy HelloWorld znajduje się w katalogu pl/naukajavy, to klasa ta należy do pakietu pl.naukajavy.

Page 20: Programowanie w środowisku graficznym- wykład 2

21.02.2018 20

PAKIETY c.d.● Pakiety klas są zwykle przechowywane w plikach JAR (Java

ARchive) lub ZIP. Pliki Jar zawierają skompresowane pliki klas i katalogi.

● Klasy zdefiniowane w nienazwanym pakiecie (tj. bez użycia dyrektywy package) mają nazwy proste np. Para.

● Przy tworzeniu większych projektów lub klas, używanych w innych programach, klasy umieszczamy w nazwanych pakietach, stosując dyrektywę package. (W NetBeans wystarczy podać nazwę pakietu w dialogu definiowania klasy, a automatycznie wygenerowany plik źródłowy będzie zawierał odpowiednią dyrektywę package) np. :

package pl.naukajavy;public class HelloWorld { public static void main(String[] args) { System.out.println("Hello World!"); }}

Page 21: Programowanie w środowisku graficznym- wykład 2

21.02.2018 21

IMPORTOWANIE KLAS

● Deklaracja importu pozwala na używanie nazw uproszczonych

import nazwa_pakietu.*; //importuje wszystkie

//nazwy klas z pakietu nazwa_pakietu

import nazwa_pakietu.KonkretnaKlasa;

//importuje nazwę klasy

np.:

import java.io.*;

class A{

File f = new File(”plik.txt”);

}

Page 22: Programowanie w środowisku graficznym- wykład 2

21.02.2018 22

IMPORTOWANIE KLAS● Klasy String i System pochodzą z pakietu java.lang. Nie

wymaga on importu, nazwy klas z tego pakietu są importowane domyślnie.

● Importowanie nazw klas nie oznacza wstawiania ich definicji do programu, umożliwia on tylko posługiwanie się nazwami skróconymi

● Import statyczny umożliwia odwołania do składowych statycznych

import static nazwa_pakietu.*;

import static nazwa_pakietu.KonkretnaKlasa;

np.: import static java.lang.System.out;

public class MojaKlasa{

public static void main(String[] args){ out.println(”krócej”); }}

Page 23: Programowanie w środowisku graficznym- wykład 2

21.02.2018 23

STRUKTURA PROGRAMU

● Program w Javie to zestaw definicji klas

● Poza ciałem klasy nie może być żadnego kodu, poza dyrektywami package, importu i komentarzami

package … //nieobowiązkowa deklaracja pakietu

import … //deklaracje importu

public class A{…}

class B{…}

● Program może być zapisany w 1 lub wielu plikach (.java) (W pliku może być tylko 1 klasa publiczna)

Page 24: Programowanie w środowisku graficznym- wykład 2

21.02.2018 24

DZIEDZICZENIE● Dziedziczenie polega na przejęciu właściwości i funkcjonalności

obiektów pewnej klasy, z ewentualną ich modyfikacją i/lub uzupełnieniem w taki sposób, by były bardziej wyspecjalizowane.

● Definicja klasy pochodnej:

atrybut_dostępu class B extends A{…}

● Klasa A jest bezpośrednią nadklasą, superklasą, klasą bazową klasy B

● Klasa B jest bezpośrednią podklasą, klasą pochodną klasy A

● Aby utworzyć klasę pochodną od klasy z innego pakietu, klasa bazowa musi być zadeklarowana jako public (W innym przypadku nie można się do niej odwołać spoza pakietu).

● Klasa może dziedziczyć tylko po jednej nadklasie.

Page 25: Programowanie w środowisku graficznym- wykład 2

21.02.2018 25

DZIEDZICZENIE ZMIENNYCH

● Podklasa z tego samego pakietu dziedziczy wszystko oprócz zmiennych private.

● Podklasa, zdefiniowana poza pakietem, w którym jest klasa bazowa, nie dziedziczy zmiennych private i zmiennych z domyślnym atrybutem dostępu.

● Tabela przedstawia jak atrybuty dostępu wpływają na dziedziczenie zmiennych, gdy podklasa jest zdefiniowana w tym samym pakiecie, co klasa bazowa i gdy podklasa jest zdefiniowana w innym pakiecie.

Pakiet 2 Pakiet 1

PodKlasa Klasa PodKlasa

Nie int a; Tak int a;

public int b; Tak public int b; Tak public int b;

protected int c;

Tak protected int c;

Tak protected int c;

Nie private int e; Nie

Page 26: Programowanie w środowisku graficznym- wykład 2

21.02.2018 26

Dziedziczenie metod

● Zwykłe metody (tzn. wszystkie metody poza konstruktorami) są dziedziczone analogicznie jak zmienne (w zależności od atrybutów).

● Konstruktory nie są nigdy dziedziczone.

● Pola klasy bazowej (najczęściej prywatne- nie mamy do nich dostępu w podklasie) inicjujemy w konstruktorze podklasy za pomocą wywołania konstruktora klasy bazowej. Co więcej, jeśli tego nie zrobimy, to kompilator sam wywoła konstruktor bezparametrowy nadklasy.

● Jawne wywołanie konstruktora klasy bazowej w konstruktorze podklasy(koniecznie jako pierwsza instrukcja) dokonuje się poleceniem

super(argl,...,argn);

Page 27: Programowanie w środowisku graficznym- wykład 2

21.02.2018 27

Dziedziczenie - przykład

● PRZYKŁAD

//definicja klasy bazowej(nadklasy)

public class Zwierze {

private String gatunek;

public Zwierze(){}//konstruktor bezparametrowy

public Zwierze(String nazwa) {

gatunek = nazwa;//new String(nazwa);

}

public void coToJest() {

System.out.println("To jest " + gatunek);

}

}

Page 28: Programowanie w środowisku graficznym- wykład 2

21.02.2018 28

Dziedziczenie – przykład c.d.// definicja klasy pochodnej

public class Pies extends Zwierze {

private String imie; // imię psa

private String rasa; // rasa

public Pies(){}//konstruktor sam wykona super()

public Pies(String toImie) {

super("Pies"); // wywołaj konstruktor nadklasy

imie = toImie; // podane imię

rasa = "Nieznana"; // domyślna rasa

}

public Pies(String toImie, String taRasa) {

super("Pies"); // wywołaj konstruktor nadklasy

imie = tolmie; // podane imię

rasa = taRasa; // podana rasa

}

}

Page 29: Programowanie w środowisku graficznym- wykład 2

21.02.2018 29

Dziedziczenie – przykład c.d.

public class Test {

public static void main(String[] args) {

Pies nowyPies = new Pies("Fido","Chihuahua"); Pies gwiazdorPies = new Pies("Lassie"); nowyPies.coToJest(); // opis gwiazdorPies.coToJest(); // i opis gwiazdora

}

}

● Klasa Pies dziedziczy po klasie Zwierze, więc obiekty klasy Pies mają również właściwości obiektów klasy Zwierze, a zatem możemy na ich rzecz używać metod zdefiniowanych w klasie Zwierze

Page 30: Programowanie w środowisku graficznym- wykład 2

21.02.2018 30

DZIEDZICZENIE-referencyjna konwersja rozszerzająca

● Zauważmy, że obiekty klasy Pies są również obiektami klasy Zwierze (mają jej wszelkie właściwości). Zatem referencje do obiektów klasy Pies możemy przypisać zmiennym oznaczającym obiekty klasy Zwierze : Pies p = new Pies(...); Zwierze z = p;

● Nazywamy to referencyjną konwersją rozszerzającą (widening reference conversion). Konwersja jest rozszerzająca, bo przekształcamy typ pochodny(referencja do obiektu podklasy) do typu szerszego (referencja do obiektu nadklasy)

● Zdolność obiektów do stawania się obiektem swojej nadklasy jest użyteczna.

● PRZYKŁAD: Załóżmy, że mamy nadklasę NadKlasa, z której wyprowadziliśmy podklasy: PodKlasa1, PodKlasa2.

Page 31: Programowanie w środowisku graficznym- wykład 2

21.02.2018 31

DZIEDZICZENIE – konwersja rozszerzająca

● Załóżmy, że mamy zdefiniowaną metodę public typ metoda(NadKlasa n1, NadKlasa n2){ …. }

● Wówczas dzięki automatycznej konwersji referencyjnej możemy wywoływać ją dla różnych rodzajów par: NadKlasa nkl1 = new NadKlasa(...); NadKlasa nkl2 = new NadKlasa(...); PodKlasa1 p1 = new PodKlasa1(...); PodKlasa2 p2 = new PodKlasa2(...); typ zm; zm=metoda(nkl1,nkl2); zm=metoda(nkl1,p1); zm=metoda(p1,p2);

● Gdyby nie było obiektowych konwersji rozszerzających, to dla każdej możliwej kombinacji par musielibyśmy napisać inną wersję metody metoda().

Page 32: Programowanie w środowisku graficznym- wykład 2

21.02.2018 32

DZIEDZICZENIE-referencyjna konwersja zwężająca

● Zauważmy, że w rozważanej powyżej metodzie

public typ metoda(NadKlasa n1, NadKlasa n2){ …}wobec parametrów n1, n2 możemy używać metod z NadKlasy, ale nie można używać metod z klas pochodnych (nawet, gdy n1, n2 wskazują na obiekty klas pochodnych)

● Referencyjna konwersja zwężająca – polega na jawnym zastosowaniu operatora rzutowania do podklasy np..:void jakasMetoda(NadKlasa n){ typ zm=((PodKlasa1)n).metodaPodKlasy1(); …}

● W przypadku, gdyby ktoś wywołał tę metodę dla obiektu podklasy PodKlasa2, zostałby wyrzucony wyjątek CastClassException i wykonanie programu zostałoby przerwane

Page 33: Programowanie w środowisku graficznym- wykład 2

21.02.2018 33

OPERATOR instanceof

● Wyrażenie ref instanceof Tma wartość true, jeśli referencja ref nie jest null i może być w fazie wykonania programu rzutowana do typu T bez zgłoszenia wyjątku CastClassException tzn. jeśli referencja ref jest typu T lub dowolnego podtypu T.

Wówczas:

void jakasMetoda (NadKlasa n){ typ zm; if(n instanceof PodKlasa1) zm = ((PodKlasa1)n).metodaPodKlasy1(); else if (n instanceof PodKlasa2) zm = ((PodKlasa2)n).metodaPodKlasy2(); …}

Page 34: Programowanie w środowisku graficznym- wykład 2

21.02.2018 34

METODA getClass()

● Innym sposobem stwierdzania typu jest zastosowanie metody getClass(). Metoda ta zwraca faktyczny typ obiektu w postaci referencji do obiektu klasy Class. Obiekty tej klasy oznaczają klasy Pies p=new Pies(”Burek”); Zwierze z=p; Class c=z.getClass();//zmienna c będzie oznaczać klasę Pies

● Aby dowiedzieć się nazwy klasy -metoda getName() Class c = z.getClass(); String nazwa = c.getName();

● Uwaga: Różnica pomiędzy instanceof, a getClass():jeśli PodKlasa1 miałaby klasę pochodną PodPodKlasa1: PodPodKlasa1 kl = new PodPodKlasa1(...);to kl instanceof PodKlasa1 zwróci true (bo brane są pod uwagę podtypy), natomiast kl.getClass().getName() zwróci napis ”PodPodKlasa1”

Page 35: Programowanie w środowisku graficznym- wykład 2

21.02.2018 35

DZIEDZICZENIE -nadpisywanie metod w klasie pochodnej

Metoda coToJest() z nadklasy Zwierze

public void coToJest(){

System.out.println("To jest " + gatunek);

} nie jest zbyt przydatna w klasie Pies,bo informuje tylko o cechach dostępnych w klasie Zwierze.

Dopiszmy zatem w klasie Pies:

public void coToJest(){ super.coToJest();//wywołanie metody bazowej //dowiemy się,że to pies, bo pole gatunek prywatne System.out.println("To jest " + imie + " z rasy " + rasa)}

Ta metoda ma tę samą sygnaturę co metoda o tej samej nazwie w klasie bazowej i nadpisuje się nad tamtą metodę. Metoda nadpisująca metodę z klasy bazowej nie może mieć atrybutu dostępu bardziej restrykcyjnego niż metoda z klasy bazowej.

Page 36: Programowanie w środowisku graficznym- wykład 2

21.02.2018 36

DZIEDZICZENIE - podsumowanie

● W Javie każda klasa może bezpośrednio dziedziczyć tylko po jednej klasie, ale pośrednio może mieć wiele nadklas, co wynika z hierarchii dziedziczenia. Ta hierarchia zawsze zaczyna się na klasie Object (której definicja znajduje się w zestawie standardowych klas Javy). Zatem w Javie wszystkie klasy pochodzą pośrednio od klasy Object. Jeśli definiując klasę, nie użyjemy słowa extends (nie zażądamy jawnie dziedziczenia) to i tak nasza klasa domyślnie będzie dziedziczyć klasę Object (tak jakbyśmy napisali class A extends Object). Zatem referencję do obiektu dowolnej klasy można przypisać zmiennej typu Object.

● Object

NadKlasa

PodKlasa2

PodKlasa1

PodPodKlasa1

Page 37: Programowanie w środowisku graficznym- wykład 2

21.02.2018 37

METODY equals() i toString()● Operator == użyty wobec obiektów porównuje referencję

● Do porównywania zawartości obiektów służy metoda public boolean equals(Object o)przedefiniowana w większości standardowych klas (np. String),która zwraca true, gdy obiekt na rzecz którego wywołano metodę ma taką samą zawartość jak obiekt, przekazany jako argument

● Dla klasy Para sami musimy ją zdefiniować, sygnatura metody musi być zawsze jak powyżej np. public class Para private int a, b;

@Override //adnotacja - nieobowiązkowa public boolean equals(Object obj){

if (this==obj) return true;

if (obj==null) return false;

if (getClass()!= obj.getClass())return false;

Para other=(Para)obj;//konwersja zwężająca

if(a!= other.a || b!=other.b)return false;

else return true; }}

Page 38: Programowanie w środowisku graficznym- wykład 2

21.02.2018 38

METODY equals() i toString()

● Do przedstawiania zawartości obiektów w postaci napisów służy metoda : public String toString()wprowadzona już w klasie Object.W naszych klasach definiujemy ją sami. Jeśli metodzie println() przekażemy jako argument referencję do obiektu, to zostanie wywołana metoda toString()

● Przykładpublic class Para{ private int a,b; //....konstruktory

@Override public String toString(){ return ”(”+a+”,”+b+”)”; } public static void main(String[] args){ Para p = new Para(1,2); System.out.println(p); }}

Page 39: Programowanie w środowisku graficznym- wykład 2

21.02.2018 39

METODA toString() - przykład

//definicja klasy bazowej(nadklasy)public class Animal { private String name; //imie zwierzaka

public Animal(){}//konstruktor bezparametrowy public Animal(String name) { this.name = name; } public String getName(){ return name; } public void setName(String name){ this.name = name; } @Override public String toString(){ return "Animal: " + name; }}

Page 40: Programowanie w środowisku graficznym- wykład 2

21.02.2018 40

METODA toString() - przykład

// definicja klasy pochodnejpublic class Cat extends Animal { private String owner;//wlasciciel kotka public Cat(){}//konstruktor sam wykona super() public Cat(String name, String owner) { super(imie); // wywołaj konstruktor nadklasy this.owner = owner; } public String getOwner(){ return owner; } public void setOwner(String owner){ this.owner = owner; } @Override public String toString(){ return super.toString() + '\n' + "Owner: " + owner; }//super.toString()-wywołanie metody toString z nadklasy