java
/obiektowo
1
Klasy
•
składowe klasy to pola i metody
•
hermetyzacja: działaj c na obiektach klasy powinni my si
posługiwa wył cznie jej metodami
•
pola klasy deklaruje si zwykle jako
private dost p do
nich mo liwy jest tylko z wn trza danej klasy m.in. z jej
metod
•
metody, które maj by wywoływane z innej klasy deklaruje
si jako
public lub protected (tylko z potomków)
•
element to pole obiektu; s to konkretne obszary pami ci
•
domy lnie, przy tworzeniu obiektów, elementy otrzymuj
warto ci: 0 (całkowite), 0 (rzeczywiste), false (boolean),
null (referencyjne)
•
void metoda() ko czy si
return; lub bez return
Typ metoda() ko czy si
return element_Typu;
•
argumenty przekazywane s metodom tylko przez warto
czyli
metoda działa na kopii, dotyczy to tak e referencji do
obiektów
•
konstruktor
o zawsze wywoływany za pomoc new
o je li ma by wywoływany spoza klasy musi by
public
o bezparametrowy automatycznie dodawany do definicji
klasy, jego ciało jest puste; nie jest dodawany
automatycznie je li w klasie zdefiniowano jakikolwiek
konstruktor
o przykład
Para p1=new Para(1,5);
1) new
tworzy obiekt do przechowywania dwóch liczb
całkowitych
2) elementy te otrzymuj warto
zero (domy lna
inicjacja)
3) dopiero teraz
wywoływany jest konstruktor klasy Para
z argumentami 1 i 5 – jego wykonanie powoduje, e
elementy obiektu otrzymaj warto ci 1 i 5
4) new zwraca referencj do nowo utworzonego obiektu
5) referencja ta podstawiana jest na zmienn p1
java
/obiektowo
2
•
this
o to referencja do nowo utworzonego obiektu (przez new –
patrz wy ej) dost pna w konstruktorze np.
class Para {
int a,b;
//…
public Para(int x, int y) {
this.a=x;
this.b=y; }
słowo
this w tym wypadku mo na pomin
, ale gdy
identyfikatory parametrów przesłaniaj (s takie same
jak) identyfikatory pól klasy to jest konieczne:
public Para(int a, int b) {
this.a=a;
this.b=b; }
o to samo dotyczy innych metod: np. p1.set(p2);
void set(Para p) {
this.a=p.a;
this.b=p.b; }
tu tak e mo na pomin
this, bo kontekst jest jasny
o gdy metoda powinna zwróci referencj do obiektu, na
rzecz którego została wywołana this jest konieczne:
Para add(Para p) {
a += p.a;
b += p.b;
return this; }
zamiast:
Para suma=new Para(0,0);
suma.add(p1); suma.add(p2); suma.add(p3);
mo na zapisa :
suma.add(p1).add(p2).add(p3);
java
/obiektowo
3
•
składowe statyczne
o pola i metody klasy deklarowane przy pomocy
static
o mo na si do nich odwoływa za pomoc :
NazwaKlasy.NazwaSkładowej np. System.exit(0)
o pola statyczne nie s zawarte w obiektach: dla ka dego
obiektu klasy istnieje tylko jeden (ten sam) obszar w
pami ci
np. je li Disk to klasa:
private static double vat;
public static void setVat(double v) {vat=v}
Disk.setVat(22.0);
Disk d1=(„Barracuda”, 120, 300.0);
o metody statyczne mog si odwoływa do innych
statycznych, ale nie wolno si odwoływa do
niestatycznych, bo obiekt mo e nie istnie
public class Main2 {
double sum(double a, double b, double c) {
return a + b + c; }
void report(double a, double b, double c) {
System.out.println("Suma " + sum(a, b, c));
public static void main(String[] args) {
double a = 12.0,
b = 14.0,
c = 4.0;
report(a, b, c); }
}
// b dzie bł d kompilacji:
non-static method report(double,double,double) cannot be
referenced from a static context report(a,b,c)
// rozwi zanie: w main() utworzy obiekt klasy i na jego rzecz
wywoła metod np.
main() { Main2 m=new Main2();
m.report(); }
o metody niestatyczne mog naturalnie odwoływa si do
pól i metod statycznych
java
/obiektowo
4
•
przy ka dym pierwszym odwołaniu do klasy (przez new, lub
odwołuj c si do zmiennej statycznej) kolejno
inicjacji
jest nast puj ca:
1. pola statyczne w kolejno ci deklaracji
2. pola niestatyczne w kolejno ci deklaracji
3. wykonanie konstruktora
Para p=new Para();
// (0,0)
Para() { a--; b--; }
// (-1,-1)
// jawna inicjacja:
int a=1, b=1;
Para() { a++; b=13; }
// (2,13)
•
zmienne lokalne
o nie wolno przesłania zmiennych lokalnych w blokach
wewn trznych:
class A {
void metoda() {
int a;
{
int a;
// niedopuszczalne
...
}
}
}
o zmienne lokalne musz mie nadane warto ci, bo nie maj
inicjacji np. poni ej bł d kompilacji:
import javax.swing.*;
public class A {
public static void main(String[] args) {
int len;
String s = JOptionPane.showInputDialog("Napis?");
if (s != null) len = s.length();
else len = -1; // ta linia konieczna bo inaczej
// kompilator da bł d:
// variable len might not have been initialized
// System.out.println("Długosc napisu : " + len);
// ^
System.out.println("Długosc napisu : " + len);
}
}
java
/obiektowo
5
•
ycie zmiennych lokalnych (na stosie): do wyj cia z bloku
ycie obiektu (dynamicznie na stercie): dopóki jaka
referencja na niego wskazuje
zwalnianie pami ci: w Javie jest automatyczne garbage
collector
•
pakiet = biblioteka klas
o klasy kompilowane bez deklaracji package nale
do
pakietu domy lnego (definiowanego przez rodowisko –
zwykle bie
cy katalog)
o pakiety maj hierarchiczn struktur chroni przed
kolizjami nazw, porz dkuj przestrze nazw
o w Javie jest ~100 pakietów, które zawieraj tysi ce
klas, pakiety te s umieszczone w plikach JAR
o kwalifikowana nazwa klasy: np. java.awt.Button,
nazwa uproszczona np. Button jest u ywana wtedy, gdy
jest obecna deklaracja import java.awt.Button;
o klasy System i String s w pakiecie java.lang.* i s
importowane domy lnie
o importowanie nazw klas nie oznacza wstawiania ich
definicji do programu ródłowego, ale jest informacj
dla kompilatora i JVM gdzie szuka definicji
kod programu mo e by tylko w klasie!
•
bardzo cz sto (zwłaszcza przy tworzeniu interfejsu
graficznego) w main() jest wywoływany tylko konstruktor,
który „robi wszystko” – je li mamy odwołania do metod w
konstruktorze, to nie trzeba specyfikowa obiektu, do
którego si odnosz (bo niejawnie jest to obiekt this)
public class B{
main() {new B();}
B() {…}
}
java
/obiektowo
6
Obiektowo
•
deklaracja np. Punkt p; nie tworzy obiektu tzn. nie wydziela
pami ci do przechowywania obiektu klasy. Sam obiekt musi by
dopiero jawnie utworzony (na stercie) przez operator
new
•
warto ci new jest referencja – zmienna p ma teraz warto
równ referencji do obiektu klasy Punkt
•
wszystkie zmienne deklarowane z nazw klasy w miejsce typu
s zmiennymi typu referencyjnego; mog one zawiera
referencje do obiektów lub wskazywa na null
•
null jest literałem typu referencyjnego (jak 2 literałem
typu int)
•
na obiektach operujemy za pomoc referencji (które na nie
wskazuj ) i metod
public class Roznica {
public static void main(String[] args) {
// operacje na zmiennych typów pierwotnych
int x, y, z;
x = 3;
y = 4;
x = y;
y = 5;
z = 5;
System.out.println(„x = „ + x+”y = „ + y + “z = „ + z);
if (x == y) System.out.println („x i y równe.”);
else System.out.println („x i y nierówne.”);
if (y == z) System.out.println („y i z równe.”);
else System.out.println („y i z nierówne.”);
// Podobne operacje na zmiennych typu referencyjnego
Para px = new Para(), py = new Para(), pz = new Para();
px.set(3,3);
py.set(4,4);
pz.set(5,5);
px = py;
py.set( 5, 5 );
System.out.print(“px: “); px.show();
System.out.print(“py: “); py.show();
System.out.print(“pz: “); pz.show();
java
/obiektowo
7
if (px == py) System.out.println („px i py równe.”);
else System.out.println („px i py nierówne.”);
if (py == pz) System.out.println („py i pz równe.”);
else System.out.println („py i pz nierówne.”);
}
}
class Para {
private int a;
private int b;
void set(int x, int y) { a = x; b = y; }
void show() { System.out.println( “( “ + a + “ , “ + b + “
)” ); }
}
//wyswietli:
x = 4y = 5z = 5
x i y nierówne.
y i z równe.
px: ( 5 , 5 )
py: ( 5 , 5 )
pz: ( 5 , 5 )
px i py równe.
py i pz nierówne.
Jak poprawnie przeczyta poni sze (w praktyce u ywamy skróty
my lowe)?
Color x=y.getBackground();
zmiennej x przypisujemy referencj do obiektu klasy Color
zwrócon przez metod getBackground(), wywołan na rzecz
obiektu, do którego referencj zawiera zmienna y
java
/obiektowo
8
Projektowanie i budowa klas
•
obiekty współdziałaj ze sob wymieniaj c komunikaty
•
komunikat to w ski i dobrze okre lony interfejs opisuj cy
współzale no
działania obiektów; komunikaty zwykle
daj
od obiektów wykonania okre lonych, wła ciwych im usług
•
hermetyzacja: dane (atrybuty) s ukryte i traktowane jako
nierozdzielna cało
z usługami zwi ksza to odporno
programu na bł dy
•
specyfikator dost pu dla zmiennych, stałych i metod:
private - dost pna tylko w klasie; atrybuty private s
nadawane przy tworzeniu obiektów i potem adna inna klasa
nie mo e ich zmieni
protected - dost pna w klasie i potomkach
public - dost pna zewsz d
zaprzyja niona - brak specyfikatora, dost pna dla wszystkich
klas pakietu
•
specyfikatory dla klas
public - dost pna zewsz d
klasa pakietowa - bez specyfikatora, dost pna tylko z klas
pakietu
•
stałe: specyfikator
final
•
odwołanie do zmiennej statycznej: NazwaKlasy.Składowa lub
gdy istnieje jaki obiekt – normalnie, tak jak przy
odwołaniu do składowych niestatycznych
•
inicjacje:
o pola klasy na zero (0, false, null)
o jawna inicjacja przy deklaracji pól
o reinicjacja w konstruktorze
•
w Javie nie mo na wykonywa instrukcji wykonywalnych (m.in.
steruj cych) poza ciałami metod, ale dwa wyj tki:
o niestatyczny blok inicjuj cy: jest to kod w nawiasach
{ } w ciele klasy poza metodami, zostanie wykonany przy
tworzeniu obiektu na etapie inicjalizacji, a przed
wywołaniem konstruktora; przydaje si gdy chcemy
zainicjalizowa pewne pola obiektu niezale nie od
java
/obiektowo
9
u ytego konstruktora przed u yciem jakiegokolwiek z
nich - nie nadu ywa , bo kod inicjalizuj cy powinien
by skupiony w jednym miejscu
o statyczny blok inicjuj cy: mo na skorzysta z dowolnych
wyra e składaj cych si ze zmiennych i stałych
statycznych oraz wywoła statycznych metod; słowo
kluczowe
static + {kod} ; wykonywany tylko raz przy
pierwszym odwołaniu si do klasy (np. u ycie metody
statycznej lub utworzenie pierwszego obiektu)
class Vehicle {
public final static int BROKEN=0, STOPPED=1, MOVING=2;
private final static String[] states =
{"ZEPSUTY", "STOI", "JEDZIE"};
private static int count;
// statyczny blok inicjacyjny za jego pomoc inicjujemy
// zmienn count w taki sposób, by numery pojazdów zaczynały
// si w zale no ci od domy lnej lokalizacji aplikacji np.
// je li aplikacja jest wykonywana w lokalizacji włoskiej
// numery zaczynaj si od 10000
static {
Locale.setDefault(Locale.ITALY);
Locale[] loc =
{Locale.UK, Locale.US, Locale.JAPAN, Locale.ITALY,};
int[] begNr = { 1, 100, 1000, 10000, };
// !
count = 200;
// je eli aplikacja działa w innej od wymienionych
// w tablicy lokalizacji, zaczynamy numery od 200
Locale defLoc = Locale.getDefault(); // domy lna lokalizacja
System.out.println("Domyslna lokalizacja: "+defLoc);
// System.out.println("_______"+loc.length);
for (int i=0; i < loc.length; i++)
if (defLoc.equals(loc[i])) {
count = begNr[i];
break; }
}
private int currNr = ++count;
private int width, height, length, weight;
private Person owner;
private int state;
// niestatyczny blok inicjacyjny - w niedziel wszystkie
// samochody inicjalnie stoj - w poniedziałek te o parzystych
java
/obiektowo
10
// numerach inicjalnie jad , nne – stoj
// w pozostałe dni tygodnia: pierwszy stworzony inicjalnie
// stoi, inne jad
{
int dayOfWeek =
Calendar.getInstance().get(Calendar.DAY_OF_WEEK);
switch (dayOfWeek) {
case Calendar.SUNDAY : state = STOPPED; break;
case Calendar.MONDAY : state =
(currNr % 2 == 0 ? MOVING : STOPPED); break;
default : state =
(currNr == 1 ? STOPPED : MOVING); break;
}
}
Vehicle() { }
Vehicle(int w, int h, int l, int ww) {
this(null, w, h, l, ww); }
Vehicle(Person p, int w, int h, int l, int ww) {
owner = p;
width = w;
height = h;
length = l;
weight = ww; }
public void start() {setState(MOVING);}
public void stop() {setState(STOPPED);}
private void setState(int newState) {
if (state == newState || state == BROKEN)
System.out.println("Nie jest mozliwe przejscie ze
stanu " + states[state] + " do stanu " + states[newState]);
else state = newState; }
public Vehicle repair() {
if (state == MOVING)
System.out.println("Nie mozna reperowa jadacego pojazdu");
else if (state != BROKEN)
System.out.println("Pojazd sprawny");
else state = STOPPED;
return this; }
public int getState() {return state;}
public static String getState(int state)
{return states[state];}
java
/obiektowo
11
public boolean isStopped() {return state == STOPPED;}
public void crash(Vehicle v) {
if (state != MOVING && v.state != MOVING)
System.out.println("Nie ma kolizji");
else { setState(BROKEN);
v.setState(BROKEN);} }
public void sellTo(Person p) {owner = p;}
public int getNr() {return currNr;}
public boolean isTooHighToGoUnder(int limit)
{return height>limit ? true:false;}
public String toString() {
String s = (owner == null ? "sklep" : owner.getName());
return "Pojazd " + currNr + " ,wlascicielem ktorego jest "
+ s + " - " + states[state]; }
static int getCount() {return count;}
static String[] getAvailableStates() {return states;}
}
class Person {
private String name;
private String pesel;
Person(String aname, String id) {
name = aname;
pesel = id; }
public String getName() { return name; }
public String getPesel() { return pesel;}
}
public class VehTest { // klasa testuj ca
static void report(String msg, Vehicle[] v) {
System.out.println(msg);
for (int i=0; i < v.length; i++)
System.out.println("" + v[i]); }
public static void main(String[] args) {
System.out.println("Dopuszczalne stany pojazdow");
String[] states = Vehicle.getAvailableStates();
for (int i = 0; i < states.length; i++)
java
/obiektowo
12
System.out.println(states[i]);
System.out.println("W programie mamy teraz pojazdow: " +
Vehicle.getCount());
Vehicle[] v = {
new Vehicle(new Person("Jan Piesio", "010268246"),
200, 150, 500, 900),
new Vehicle(new Person("Stefan Kot", "010262241"),
210, 250, 800, 1900),
new Vehicle(200, 230, 300, 600),
};
System.out.println("W programie mamy teraz pojazdow: " +
Vehicle.getCount());
report("Na poczatku", v);
System.out.println("Pojazd 3 zostaje sprzedany Ambrozemu");
v[2].sellTo(new Person("Ambrozy", "000000"));
for (int i=0; i < v.length; i++) v[i].start();
report("Po wyruszeniu", v);
// Czy moga przejechac pod wiaduktem 220cm?
for (int i=0; i < v.length; i++)
if (v[i].isTooHighToGoUnder(220)) v[i].stop();
report("Komu udalo sie przejechac pod wiaduktem?", v);
// zatrzymane wyruszaja w objazd
for (int i=0; i < v.length; i++)
if (v[i].isStopped()) v[i].start();
report("Po wyruszeniu w objazd", v);
v[0].crash(v[1]);
// kolizja
report("Po kolizji", v);
System.out.println("Piesio probuje ruszyc");
v[0].start();
System.out.println("Piesio sprzedaje pojazd Krowce.
Ta go reperuje i jedzie");
v[0].sellTo(new Person("Anna Krowka", "121212908"));
v[0].repair().start();
report("Ostatecznie",v);
System.out.println("Stan pojazdu 3 " +
Vehicle.getState(v[2].getState()));
} }
java
/obiektowo
13
•
przeci
anie
załó my, e s zdefiniowane metody: show(short) i show(int)
przy wywołaniu show(char) b dzie promocja char do int i
wywołany zostanie show(int) [a przecie char jest bli ej do
short]
•
konstruktor bezparametrowy dodawany jest sam, ale je li
zdefiniowano jaki konstruktor to konstruktor bezparametrowy
nie jest dodawany automatycznie (wtedy powinno si go doda ,
by unikn
bł dów przy dziedziczeniu klasy i zagwarantowa
mo liwo
traktowania obiektów klasy jako ziarna JavaBeans)
•
konstruktor mo na wywoływa z innego konstruktora za pomoc
this(lista_parametrów) – musi to by pierwsza instrukcja w
ciele konstruktora np.
Auto(int a, int b, int c, int d) {
this(null, a, b, c, d); }
•
konieczne u ycie this:
o przy przesłoni ciu nazw zmiennych oznaczaj cych pola
private int height;
public Auto (int height) {this.height=height;}
o gdy metoda musi zwraca TEN obiekt
Auto repair() {
//..
return this; }
i wtedy mo na szybko pisa :
Auto vv;
vv.repair().jedz();
o wywołanie konstruktora z innego konstruktora
java
/obiektowo
14
Dziedziczenie
•
s dwa sposoby ponownego wykorzystania klas:
o kompozycja: definiowanie pól obiektowych w klasie
(obiekt w innym obiekcie) – małe nakłady na kodowanie,
bo korzystamy z gotowych klas; relacja: cało
-cz
o dziedziczenie: przej cie wła ciwo ci i funkcjonalno ci
obiektów innej klasy i ewentualna modyfikacja tych
wła ciwo ci i funkcjonalno ci dla wi kszej
specjalizacji; relacja generalizacja-specjalizacja
•
je li nadklasa ma pola prywatne, to nie ma do nich dost pu –
mo na je zainicjalizowa z konstruktora klasy pochodnej
u ywaj c:
super(lista_argumentów); musi to by pierwsza
instrukcja konstruktora
•
je li w konstruktorze potomka nie ma super() to zostanie
wywołany konstruktor bezparametrowy rodzica
•
przewiduj c, e tworzona klasa mo e by kiedy dziedziczona,
warto dostarczy konstruktor bezparametrowy, bo musi istnie
domy lny sposób inicjacji jej obiektów
class s { // ułatwienie dla wypisywania
static void ay(String s) {System.out.println(s);}
}
class A {
A() {s.ay("Konstruktor A");}
A(String t) {s.ay("Konstruktor A z parametrem String="+t);}
}
class B extends A {
B() {s.ay("Konstruktor B");}
B(int i) {s.ay("Konstruktor B z parametrem int = " + i);}
B(String t) { super(t);
s.ay("Konstruktor B z parametrem String = " + t); }
}
class C extends B { }
class Test {
public static void main(String[] arg) {
s.ay("Tworzenie obiektu B - B():");
new B();
s.ay("Tworzenie obiektu B - B(int)");
java
/obiektowo
15
new B(1);
s.ay("Tworzenie obiektu B - (Strng)");
new B("Ala");
s.ay("Tworzenie obiektu C:");
new C(); }
}
// wypis:
Tworzenie obiektu B - B():
Konstruktor A
Konstruktor B
Tworzenie obiektu B - B(int)
Konstruktor A
Konstruktor B z parametrem int = 1
Tworzenie obiektu B - (Strng)
Konstruktor A z parametrem String = Ala
Konstruktor B z parametrem String = Ala
Tworzenie obiektu C:
Konstruktor A
Konstruktor B
•
na rzecz obiektu potomka mo na u ywa : metod własnych
potomka, metod rodzica przedefiniowanych w potomku, metod
nieprywatnych rodzica
•
odwołanie do metody klasy bazowej, która w klasie pochodnej
jest przedefiniowana jest przez:
super.metoda();
•
super.x; odwołanie do pola z nadklasy
•
przeci
enie: ta sama nazwa, ale inna lista/typ parametrów
•
przesłanianie: w zasi gu deklaracji zmiennej, metody lub
klasy (typu) pojawia si inna deklaracja tego identyfikatora
•
przedefiniowanie: pozostawienie sygnatury (nazwa+lista
parametrów), ale zmiana np. ciała metody w potomku; typ
wyniku taki sam jak w rodzicu
•
pokrycie: dostarczenie w podklasie metody
statycznej
(niestatycznych nie dotyczy) o tej samej sygnaturze jak
metoda statyczna z nadklasy (czyli metody statyczne nie mog
by przedefiniowane, ale mog by pokryte); je li w potomku
metoda jest statyczna a u rodzica ta sama sygnatura była
niestatyczna to bł d kompilacji
•
pokrycie pola: deklaracja w podklasie pola o takim samym
identyfikatorze jak pole z nadklasy; pole statyczne mo e
pokry pole niestatyczne, pole pokrywaj ce pole rodzica mo e
mie inny typ
java
/obiektowo
16
•
w sytuacji dziedziczenia u ywa si : przedefiniowanie
(metody) i pokrycie (metody lub pola)
•
metody przedefiniowane s wywoływane polimorficznie;
pokrycie oznacza tylko zast pienie wywołania metody pokrytej
•
przeci
enie nie wyklucza przedefiniowania np.
class A {
public metodaA(par1, par2) { //...}
public metodaA(par1) { //... } // przeci
enie
}
class B extends A {
public metodaA(par1, par2, par3) { //.. } // przeci
enie
public metodaA(par1) { //inne ciało ni w nadklasie}
// przedefiniowanie
}
•
metoda prywatna nie mo e by pokryta ani przedefiniowana w
podklasie: zatem ta sama sygnatura metody w podklasie to
niezale ny byt i mo e mie inny typ wyniku
•
przy przedefiniowaniu lub pokrywaniu metod:
o dost pu nie mo na zw
a tylko dost p musi by taki sam
albo rozszerzony np. protected protected lub public
o trzeba zachowa zgodno
typów zgłaszanych wyj tków i
deklarowanych w klauzuli
throws
java
/obiektowo
17
Konwersje referencyjne
•
referencyjna konwersja rozszerzaj ca = zdolno
do stawania
si obiektem nadklasy – dzi ki temu mo na stosowa
uniwersaln metod z nadklasy do obiektów z podklas (nie
trzeba pisa dla ka dej klasy osobno oraz mo na porównywa
obiekty z ró nych podklas np. ró nic cen ksi
ki i gazety
jako pochodnych publikacji)
•
obiektowe konwersje rozszerzaj ce dokonywane s
automatycznie przy:
o przypisywaniu zmiennej referencyjnej do zmiennej
referencyjnej obiektu klasy pochodnej np.
public class A {}
public class B extends A { metoda_z_B(); ... }
B objB=new B();
A aa=objB;
// przekształcenie typu pochodnego do wy szego
o przekazywaniu metodzie argumentu typu: referencja do
obiektu nadklasy
o podstawianiu wyniku metody do referencji na obiekt
nadklasy
•
zaw
aj ce konwersje referencyjne: u ywa si eby mo na było
u ywa metod klasy podrz dnej dla „rozszerzonego w gór ”
obiektu np.
B bb=
(B)aa; // bez jawnej konwersji poni ej bł d kompilacji
bb.metoda_z_B();
•
konwersja do niewła ciwego typu w trakcie wykonywania to
zgłoszony wyj tek
ClassCastException
•
operator
instanceof: zmienna instanceof klasa zwraca
true gdy zmienna jest referencj do obiektu nale
cego do
klasy
java
/obiektowo
18
•
w Javie wszystkie klasy pochodz po rednio od klasy Object
(zatem nawet je li nie ma extends to i tak jest
class A
extends Object)
•
x instanceof Object jest true dla dowolnej referencji
•
x instanceof Klasa jest true je li x jest obiektem Klasy
oraz rodziców
•
wychodz c z zało e :
1) ka da klasa w Javie dziedziczy po Object
2) dla dowolnego obiektu mo na zastosowa konwersj
rozszerzaj c do Object,
mo na w tablicy umie ci referencje do dowolnych obiektów
(ale tylko obiektów a nie typów podstawowych) np.:
Object[] tab=new Object[2];
tab[0]=”Kowalski”;
tab[1]=new Integer(30);
// alternatywnie:
// Object tab[] = {„Kowalski”, New Integer(30)};
for (int i=0; i<tab.length; i++)System.out.println(tab[i]);
// wypisanie mo liwe, poniewa Object definiuje metod
// toString(), któr przedefiniowuj Integer oraz String
•
aby zastosowa specyficzne metody danej klasy trzeba
rozpozna obiekty przez instanceof np.:
if (tab[1] instanceof Integer) i=tab[1].intValue();
•
powy sze dotyczy operatorów, np. „+” nie mo na stosowa
wobec Object (bo co to znaczy doda dwa obiekty?) wtedy
trzeba sprawdzi instanceof i zaw zi z Object do tej klasy
(np. do String – tam „+” oznacza konkatenacj )
public class Game1 {
public static void main(String[] args) {
String[] name = { "Ala", "Ela", "Jan"};
int[] points = { 10, 12, 11 };
Object[] tab = new Object[name.length*2];
int k = 0;
for (int i=0; i<name.length; i++) {
tab[k++] = name[i];
tab[k++] = new Integer(points[i]); }
System.out.println("W grze punkty uzyskali: ");
for (int i=0; i <tab.length; i+=2)
java
/obiektowo
19
System.out.println(tab[i].toString() + " " +
tab[i+1].toString());
String players = "";
int pointSum = 0;
for (int i=0; i < tab.length; i++) {
if (tab[i] instanceof String)
players += " " + (String) tab[i];
else if ( tab[i] instanceof Integer)
pointSum += ((Integer) tab[i]).intValue();
}
System.out.println("Grali: " + players);
System.out.println("Zdobyli ł cznie: "+pointSum+" pkt.");
}}
•
new klasaA[] {refB, refC, ...} wyra enie ad hoc
tworz ce tablic typu klasaA i inicjuj ce j referencjami
wskazuj cymi na obiekty z klasyA lub klas potomków
o najcz
ciej stosuje si na li cie argumentów wywołania
metody mo na w ten sposób uzyska efekt wywołania
metody ze zmienn liczb i typem argumentów np.
class Car extends Vehicle {
public final static int BROKEN=0, STOPPED=1, MOVING=2;
private final static String[] states =
{"ZEPSUTY", "STOI", "JEDZIE"};
private int state = STOPPED;
static void reportState(Vehicle[] v) {
for (int i=0; i<v.length; i++)
System.out.println(Vehicle.getState(v[i].getState()));
}
public int getState() { return state; }
public static String getState(int state)
{return states[state];}
}
class Bike extends Vehicle {//...}
public class Testy {
public static void main(String[] a) {
Car c=new Car(), d=new Car();
Bike b=new Bike();
Car.reportState(new Vehicle[] {c,d,b}); // symulacja wywołania
}} // metody ze zmienn liczb argumentów
java
/obiektowo
20
Polimorfizm
•
metoda virtualna: wi zanie odwoła z kodem nast puje w fazie
wykonania a nie kompilacji (dynamic/late binding) i
realizowane jest za pomoc ukrytego w obiekcie pola,
wskazuj cego na jego prawdziwy typ
•
odwołania do metod wirtualnych s polimorficzne tzn. efekt
odwołania zale y od obiektu, na rzecz którego jest
wywoływana
•
wszystkie metody w Javie s wirtualne oprócz:
o metod statycznych (bo nie dotycz obiektów)
o metod deklarowanych jako final, co znaczy, e posta
metody jest ostateczna i nie mo e by przedefiniowana w
klasie pochodnej (a jak nie ma przedefiniowania to
niepotrzebna jest wirtualno
)
o metod prywatnych (bo one nie mog by przedefiniowane,
wi c polimorfizm jest wykluczony)
Car c=new Car();
Vehicle v=c;
// konwersja rozszerzaj ca
v.start();
// je li start() zdefiniowane jest w
// Vehicle oraz Car, to która wzi ta?
// wzi ta z klasy Car (start() jest tutaj metod wirtualn )
•
metoda abstrakcyjna:
o nie ma implementacji (ciała) i jest ze specyfikatorem
abstract
o pisze si je li konkretna implementacja nie jest
jeszcze znana lub nie chcemy ju przes dza , ale w
ka dej klasie pochodnej ma ta metoda wyst powa
o konkretyzacje nast puj w klasach pochodnych
o domy lnie jest wirtualna
•
klasa abstrakcyjna:
o musi by opatrzona specyfikatorem
abstract
o nie mo na tworzy obiektów takiej klasy
o nie musi mie metod abstrakcyjnych
o je li w klasie zadeklarowano jak kolwiek metod
abstrakcyjn klasa musi by abstrakcyjna
java
/obiektowo
21
Interfejs
•
problem wielodziedziczenia:
class A { public int a; }
class B extends A { //ma pole a}
class C extends A { //ma pole a}
class D extends B,C {
//element a z której klasy? B czy C czy A?}
// dlatego wielodziedziczenie w Javie zabronione
•
interfejs
o to „biedniejsza” klasa nie zawieraj ca pól tylko
publiczne, abstrakcyjne metody i/lub publiczne stałe
statyczne
o jest deklarowana za pomoc słowa kluczowego
interface
o interfejs klasy to sposób komunikowania si z jej
obiektami (inaczej: zestaw jej metod dost pnych z
poziomu innej klasy)
interface Speakable {
int QUIET=0; // nie trzeba pisa specyfikatorów,
// bo domy lnie
public static final
int LOUD=1;
String getVoice(int voice); // nie trzeba pisa
// public abstract, bo to jest
} // w interfejsie domy lne
interface Moveable {
void start();
void stop(); }
•
implementacja interfejsu w klasie:
o to zdefiniowanie w tej klasie wszystkich (!) metod
interfejsu, albo klasa musi by abstrakcyjna
o klasa mo e implementowa dowoln liczb interfejsów:
class A extends B
implements Interfejs1, Interfejs2
{...}
o interfejs, podobnie jak klasa, wyznacza typ zmiennej
mo emy wi c robi konwersje oraz u ywa operatora
instanceof
java
/obiektowo
22
class Zwierz {
String name = "nieznany";
Zwierz() { }
Zwierz(String s) { name = s; }
String getTyp() { return "Jakis zwierz"; }
String getName() { return name; }
String getVoice() { return "?"; }
void speak() {
System.out.println(getTyp()+" "+getName()+" mówi
"+getVoice());
}
}
class Pies extends Zwierz implements Speakable, Moveable {
Pies() {}
Pies(String s) {super(s);}
String getTyp() {return “Pies”;}
public String getVoice(int voice) {
if (voice==LOUD) return “HAU, HAU”;
else return “hau, hau”; }
void run(Moveable m) {
m.start();
if (m instanceof Pies) ((Pies)m).merda(); }
void merda() {System.out.println("...merdanie...");}
public void start()
{System.out.println(“Pies “+name+” biegnie”);}
public void stop()
{System.out.println(“Pies “+name+” stanal”);}
}
public class Interfejsy {
public static void main(String[] a) {
Pies kuba = new Pies("Kuba"); // kuba jest typu: Zwierz i
// Speakable i Moveable
kuba.start(); // "Pies Kuba biegnie"
System.out.println(kuba.getVoice(Speakable.LOUD));
kuba.stop(); // "Pies Kuba stan ł"
kuba.run(kuba); // to tylko aby pokaza działanie run()
// 1) niejawna konwersja w gór Pies Moveable
// 2) polimorficzne wywołanie metody start()
// na rzerz Moveable a faktycznie na rzecz Pies
// 3) konwersja zw
aj ca do Pies by dało si wywoła merda()
} }
java
/obiektowo
23
•
dzi ki koncepcji interfejsów uzyskuje si poszerzenie
polimorfizmu, poniewa polimorficzne odwołania s mo liwe
nie tylko „wzdłu ” hierarchii dziedziczenia, ale równie w
poprzek np. Car te mo e implementowa Moveable
Adapter
•
adapter to klasa implementuj ca interfejs w sposób, który
ułatwia implementacj tego interfejsu w innej klasie np. w
taki sposób, e ciała metod s puste
•
gdy w klasie musimy zaimplementowa interfejs z wieloma
metodami, a potrzebujemy tylko niektórych z tych metod, to
mo emy utworzy adapter, a nast pnie dziedziczy go w
naszych klasach przedefiniowuj c za ka dym razem tylko
interesuj ce nas metody (oszcz dno
pisania wszystkich
metod)
•
w pakietach standardowych Javy jest wiele rozbudowanych
interfejsów i odpowiadaj cych im adapterów np. w pakietach
obsługi zdarze
•
adapter jest u yteczny gdy wykorzystujemy go dziedzicz c w
anonimowych klasach wewn trznych
interface RozbudowanyInterfejs {
void met190;
void met2();
…
void metN(); }
class NaszAdapter implements RozbudowanyInterfejs {
public void met1() { }
public void met2() { } // puste definicje wszystkich klas
…
public void metN() { } }
class A extends NaszAdapter {
public void met2() { // nam potrzebna tylko ta
… // metoda, a bez adaptera trzeba
} // by implementowa wszystkie
}