JAVA- wykład 2

Transkrypt

JAVA- wykład 2
JAVA- wykład 2
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
2008
●
A. Zoła, Programowanie w języku Java, 2004
http://fatcat.ftj.agh.edu.pl/~palka/public/java_pl.pdf
1. Klasy i obiekty w Javie
Definiowanie 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
14.10.2015
Dorota Pylak - Aplikacje w Javie-cz 2
2
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_zmiennej [inicjator];
●
Przykład
public class Para {
private int a;
private int b; // = 6;
//...
}
14.10.2015
Dorota Pylak - Aplikacje w Javie-cz 2
3
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
}
}
14.10.2015
Dorota Pylak - Aplikacje w Javie-cz 2
4
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.
14.10.2015
Dorota Pylak - Aplikacje w Javie-cz 2
5
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).
14.10.2015
Dorota Pylak - Aplikacje w Javie-cz 2
6
KONSTRUKTORY c.d.
●
PRZYKŁAD
public class Para{
private int a, b;
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);
14.10.2015
//para 5 5
Dorota Pylak - Aplikacje w Javie-cz 2
7
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
PRZYKŁADY
●
metoda main – musi być statyczna ponieważ od niej zaczyna
się wykonywanie programu, a w tym momencie nie istnieje
jeszcze żaden obiekt.
14.10.2015
Dorota Pylak - Aplikacje w Javie-cz 2
8
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 argumenty
public class PrintStream{
. . .
public void println(String s){...}
}
14.10.2015
Dorota Pylak - Aplikacje w Javie-cz 2
9
SKŁADOWE STATYCZNE c.d.
Zatem
●
System.out to statyczne pole klasy System
●
println to metoda używana na rzecz tego obiektu
Stąd: System.out.println(String s)
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ć)
14.10.2015
Dorota Pylak - Aplikacje w Javie-cz 2
10
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.
14.10.2015
Dorota Pylak - Aplikacje w Javie-cz 2
11
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
14.10.2015
Dorota Pylak - Aplikacje w Javie-cz 2
12
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+”)”);
}
14.10.2015
Dorota Pylak - Aplikacje w Javie-cz 2
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).
14.10.2015
Dorota Pylak - Aplikacje w Javie-cz 2
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)
14.10.2015
Dorota Pylak - Aplikacje w Javie-cz 2
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.
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ę
●
Obiekt na rzecz którego wywołano metodę, jest wewnątrz metody
reprezentowany słowem kluczowym this.
14.10.2015
Dorota Pylak - Aplikacje w Javie-cz 2
16
SŁOWO KLUCZOWE this
●
Metoda zwracająca referencję do obiektu na rzecz którego
została wywołana, np. metoda dodająca parę przekazaną jako
argument do pary, na rzecz której wywołano metodę
Para add(Para p){
a+=p.a; b+=p.b;
return this;
}
Przykładowe wykorzystanie powyższej metody:
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żyte jako pierwsza instrukcja konstruktora
pozwala wywołać w nim inny konstruktor
14.10.2015
Dorota Pylak - Aplikacje w Javie-cz 2
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.
14.10.2015
Dorota Pylak - Aplikacje w Javie-cz 2
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).
14.10.2015
Dorota Pylak - Aplikacje w Javie-cz 2
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.
14.10.2015
Dorota Pylak - Aplikacje w Javie-cz 2
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!");
}
}
14.10.2015
Dorota Pylak - Aplikacje w Javie-cz 2
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”);
}
14.10.2015
Dorota Pylak - Aplikacje w Javie-cz 2
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.:
14.10.2015
import static java.lang.System.out;
public class MojaKlasa{
public static void main(String[] args){
out.println(”krócej”);
}
}
Dorota Pylak - Aplikacje w Javie-cz 2
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)
14.10.2015
Dorota Pylak - Aplikacje w Javie-cz 2
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.
14.10.2015
Dorota Pylak - Aplikacje w Javie-cz 2
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
public int b;
protected int
c;
Nie
Klasa
int a;
Tak
PodKlasa
int a;
Tak
public int b;
Tak
public int b;
Tak
protected int
c;
private int e;
Tak
protected int
c;
Nie
14.10.2015
Nie
Dorota Pylak - Aplikacje w Javie-cz 2
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);
14.10.2015
Dorota Pylak - Aplikacje w Javie-cz 2
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);
}
}
14.10.2015
Dorota Pylak - Aplikacje w Javie-cz 2
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
}
}
14.10.2015
Dorota Pylak - Aplikacje w Javie-cz 2
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
14.10.2015
Dorota Pylak - Aplikacje w Javie-cz 2
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.
14.10.2015
Dorota Pylak - Aplikacje w Javie-cz 2
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().
14.10.2015
Dorota Pylak - Aplikacje w Javie-cz 2
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 błąd
CastClassException i wykonanie programu zostałoby
przerwane
14.10.2015
Dorota Pylak - Aplikacje w Javie-cz 2
33
OPERATOR instanceof
●
Wyrażenie
ref instanceof T
ma 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()
…
}
●
14.10.2015
Dorota Pylak - Aplikacje w Javie-cz 2
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”
14.10.2015
Dorota Pylak - Aplikacje w Javie-cz 2
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.
14.10.2015
Dorota Pylak - Aplikacje w Javie-cz 2
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
PodKlasa1
PodKlasa2
PodPodKlasa1
14.10.2015
Dorota Pylak - Aplikacje w Javie-cz 2
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 a, b;
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;
}
}
14.10.2015
Dorota Pylak - Aplikacje w Javie-cz 2
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ład
public class Para{
private int a,b;
//....konstruktory
public String toString(){
return ”(”+a+”,”+b+”)”;
}
public static void main(String[] args){
Para p=new Para(1,2);
System.out.println(p);
}
}
14.10.2015
Dorota Pylak - Aplikacje w Javie-cz 2
39