11. Implementace OOP v Jav∞
11.1. Objekt
Program v Jav∞ je staticky strukturovßn na t°φdy, jejich╛ instance (objekty)
za b∞hu dynamicky programu vznikajφ a zanikajφ. Objekt je nejprve vytvo°en
(instanciovßn), nßsledn∞ m∙╛e b²t pou╛φvßn a nakonec je zru╣en.
11.1.1. Vytvo°enφ objektu
K vytvo°enφ objektu slou╛φ operßtor new, kter² mß syntaxi:
new volßnφKonstruktoru
Operßtor alokuje pam∞╗ pro objekt a zavolß konstruktor (viz
11.2.3.), co╛ je specißlnφ metoda, kterß provßdφ inicializaci
objektu. JmΘno konstruktoru je v╛dy shodnΘ se jmΘnem t°φdy objektu.
Priklad 11.1. |
new String("ahoj");
vytvo°φ objekt t°φdy String a inicializuje ho konstruktorem
s parametrem "ahoj".
|
|
Operßtor new vracφ referenci, odkazujφcφ na vytvo°en²
objekt. Tato reference se p°i vytvo°enφ objektu obvykle zßrove≥
uklßdß (1) do referenΦnφ
prom∞nnΘ (viz 7.2.):
Priklad 11.2. |
String retezec; // deklarace prom∞nnΘ
retezec = new String("ahoj"); // p°i°azenφ reference
nebo zkrßcen∞:
String retezec = new String("ahoj");
|
|
11.1.2. Pou╛φvßnφ objektu
Pou╛φvßnφ objektu spoΦφvß ve volßnφ metod a p°φmΘ manipulaci se
Φlensk²mi prom∞nn²mi. Pro p°φstup k prom∞nnΘ nebo metod∞ se pou╛φvß teΦkovß
notace:
reference.jmΘnoProm∞nnΘ
reference.volßnφMetody
Priklad 11.3. |
String retezec = new String("ahoj"); // vytvo°enφ objektu
retezec = retezec.concat("!"); // volßnφ metody
Metoda concat() vracφ nov² °et∞zec, kter² vznikne
p°ipojenφm parametru na konec °et∞zce. V²sledek se p°i°adφ do prom∞nnΘ
retezec.
|
|
Je mo╛nΘ pou╛φt i vφcenßsobnou p°φstupovou konstrukci:
Priklad 11.4. |
int delka = retezec.trim().length();
Metoda trim() vracφ referenci na nov² °et∞zec (instanci t°φdy
String), kter² vznikl z p∙vodnφho o°φznutφm prßzdn²ch znak∙. Metoda
length() vracφ dΘlku °et∞zce (typ int). Prom∞nnΘ delka se
tedy p°i°adφ dΘlka °et∞zce retezec po o°φznutφ metodou trim().
P°edchozφ zßpis lze p°epsat jako:
String orezanyRetezec = retezec.trim();
int delka = orezanyRetezec.length();
|
|
11.1.3. Zru╣enφ objektu
Java neumo╛≥uje p°φmΘ ru╣enφ (dealokaci) objektu. Objekt je zru╣en automaticky
a╛ tehdy, neexistuje-li na n∞j reference. Jsou nap°φklad ru╣eny
v╣echny objekty lokßlnφch prom∞nn²ch p°i ukonΦenφ metody. "RuΦnφ"
zneplatn∞nφ reference se provede p°i°azenφm hodnoty null p°φslu╣nΘ
referenΦnφ prom∞nnΘ.
Priklad 11.5. |
String retezec = new String("ahoj");
retezec = null; // zneplatn∞nφ reference -- objekt bude zru╣en
|
|
Tento automatick² mechanismus ru╣enφ objekt∙ je znßm pod nßzvem garbage
collection ("·klid smetφ"). Jeho v²hoda spoΦφvß v nemo╛nosti
dealokovat ji╛ dealokovan² prostor nebo do n∞j zapisovat, co╛ b²vß v jin²ch
jazycφch zdrojem mnoha nep°φjemn²ch chyb. ┌klid se provßdφ bu∩to synchronn∞, tzn. a╛ p°i nedostatku pam∞ti pro
dal╣φ alokace, nebo asynchronn∞ na pozadφ, pokud to danß platforma
umo╛≥uje (Unix, Windows95/NT). V programu lze o spu╣t∞nφ ·klidu po╛ßdat
volßnφm metody System.gc(), nap°φklad v dob∞, kdy program neprovßdφ
v²poΦty.
Je╣t∞ p°ed vlastnφm zru╣enφm objektu se zavolß metoda finalize() (2) (je-li definovßna), kde m∙╛e programßtor ulo╛it obsah prom∞nn²ch
do souboru apod. Deklarace tΘto metody musφ vypadat nßsledovn∞:
protected void finalize() throws Throwable
P°i ru╣enφ objektu nedochßzφ ke z°et∞zenφ volßnφ metod finalize() jako
je tomu u konstruktor∙ p°i vytvß°enφ objektu (viz 11.2.3.).
11.2. T°φda
Pro ka╛d² objekt musφ b²t p°ed jeho vytvo°enφm deklarovßna t°φda, a╗
u╛ navr╛enß v programu nebo knihovnφ. Knihovnφ t°φdy jsou ulo╛eny
v balφcφch (viz kap. 12.).
11.2.1. Deklarace t°φdy
Nejjednodu╣╣φ deklarace t°φdy mß syntaxi:
class JmΘnoT°φdy {
// t∞lo t°φdy
}
Identifikßtor JmΘnoT°φdy slou╛φ jako objektov² typ, nap°φklad v deklaraci
referenΦnφ prom∞nnΘ (viz 7.2.). V t∞le t°φdy mezi slo╛en²mi
zßvorkami mohou b²t deklarace Φlensk²ch prom∞nn²ch
(viz 11.2.4.) a/nebo deklarace a definice metod
(viz 11.2.2.) (3) - obvykle v tomto po°adφ, ale nenφ to vy╛adovßno. V╣imn∞te
si, ╛e za uzavφrajφcφ zßvorkou deklarace t°φdy nenφ st°ednφk. Specißlnφm p°φpadem je t°φda, kterß neobsahuje metody. Ta pak slou╛φ jako
klasickß datovß struktura (record v Turbo Pascalu, struct v C).
Obecnß deklarace t°φdy vypadß takto:
[ modifikßtory ] class jmΘnoT°φdy
[extends jmΘnoRodiΦovskΘT°φdy ]
[implements seznamRozhranφ ] {
// t∞lo t°φdy
}
Priklad 11.7. |
Deklarace ve°ejnΘ t°φdy Appletik, jejφ╛ rodiΦovskou je t°φda
java.applet.Applet, a kterß implementuje rozhranφ Cloneable
a Runnable (z balφku java.lang) vypadß takto:
public class Appletik extends java.applet.Applet
implements Cloneable, Runnable {
public void run() { // ...
}
// ...
}
Rozhranφ Runnable obsahuje metodu run, a proto musφ
t°φda Appletik jejφ definici obsahovat. Rozhranφ Cloneable je
prßzdnΘ a slou╛φ jen k identifikaci t°φdy (jejφ instance je mo╛nΘ klonovat
- viz 11.5.).
|
|
11.2.2. Metody
Nejjednodu╣╣φ definice metody mß tvar:
Nßvratov²Typ jmΘnoMetody ( parametry ) {
// t∞lo metody
}
- Nßvratov²Typ musφ b²t n∞kter² datov² typ z kap. 7..
Nßvrat z metody a p°φpadnΘ p°edßnφ nßvratovΘ hodnoty zp∙sobφ p°φkaz return (viz 9.13.). Je-li nßvratov²m typem void, metoda nevracφ
hodnotu.
- jmΘnoMetody musφ b²t platn² identifikßtor. Pokud majφ v jednΘ
t°φd∞ dv∞ metody shodnß jmΘna, musφ mφt odli╣n² poΦet a/nebo typ parametr∙ -
tzv. p°et∞╛ovßnφ metod (overloading). P°i volßnφ p°etφ╛enΘ
metody p°ekladaΦ na zßklad∞ argument∙ rozhodne, kterou volat. Dφky p°et∞╛ovßnφ
nemusφ existovat r∙zn∞ pojmenovanΘ metody, jejich╛ funkce je prakticky shodnß:
Priklad 11.8. |
Argumentem metody System.out.println(), kterß provßdφ v²pis na
standardnφ v²stup, m∙╛e b²t prom∞nnß kterΘhokoliv zßkladnφho datovΘho typu
nebo nic.
System.out.println(); // od°ßdkuje
System.out.println("ahoj"); // vypφ╣e ahoj (1)
System.out.println(12345); // vypφ╣e 12345 (2)
Ve v╣ech p°φpadech se jednß o volßnφ jinΘ p°etφ╛enΘ metody - p°ekladaΦ se
rozhoduje na zßklad∞ argument∙ - prvnφ p°φpad se li╣φ poΦtem argument∙, druhΘ
dva jejich typem: (1) p°edßvß °et∞zec, (2) celΘ Φφslo.
|
|
- Formßlnφ parametry metody:
- Je-li jmΘno parametru stejnΘ jako jmΘno ΦlenskΘ prom∞nnΘ, dochßzφ
k jejφmuzastφn∞nφ (hiding) parametrem. K explicitnφmu p°φstupu
ke ΦlenskΘ prom∞nnΘ pak slou╛φ operßtor this (5) (viz tΘ╛ 11.8.), kter²
vracφ referenci objektu na sebe:
Priklad 11.10. |
class Trida {
int x;
Trida (int x) { // zastφn∞nφ ΦlenskΘ prom∞nnΘ x parametrem
this.x = x; // p°i°azenφ hodnoty parametru ΦlenskΘ prom∞nnΘ x
// ...
}
}
|
|
Obecnß deklarace metody vypadß takto:
[ prßva ] [static] [abstract] [final] [native]
[synchronized] Nßvratov²Typ jmΘnoMetody ( parametry )
[throws seznamV²jimek ]
- prßva - tato polo╛ka urΦuje p°φstupnost metody vn∞ t°φdy
a pravidla pro d∞diΦnost. Metoda m∙╛e b²t bu∩ ve°ejnß (public),
chrßn∞nß (protected), soukromß (private) nebo
nemusφ mφt prßva specifikovßna v∙bec (default access).
Vφce viz 11.3. a 11.4..
- static - oznaΦuje statickou metodu.
StatickΘ metody je mo╛nΘ narozdφl od nestatick²ch volat i tehdy, neexistuje-li
╛ßdnß instance danΘ t°φdy. Mohou v╣ak p°φmo manipulovat pouze se statick²mi
(a sv²mi lokßlnφmi) prom∞nn²mi.
Volßnφ statickΘ metody mß tvar:
[ JmΘnoT°φdy. ] jmΘnoMetody ( parametry );
JmΘnoT°φdy se nemusφ specifikovat uvnit° t°φdy, kterß statickou metodu
definuje.V jednΘ t°φd∞ nem∙╛e b²t definovßna shodn∞ pojmenovanß statickß i nestatickß
metoda se stejn²m poΦtem a typem parametr∙ - jinak dojde k chyb∞ p°i
p°ekladu.
- abstract - metody deklarovanΘ jako abstraktnφ nemajφ
v danΘ t°φd∞ t∞lo a musφ b²t definovßny a╛ potomky t°φdy. T°φda, kterß
obsahuje abstraktnφ metody, nem∙╛e b²t instanciovßna a musφ b²t rovn∞╛
deklarovßna jako abstraktnφ (viz 11.2.1.).
Priklad 11.11. |
abstract class A {
abstract void metoda(); // deklarace abstraktnφ metody
}
|
|
- synchronized - viz 16.5.2..
- final - oznaΦuje koncovou metodu. Koncovß metoda nesmφ
b²t potomky p°ekryta.
- native - nativnφ metody umo╛≥ujφ slouΦit programy psanΘ
v Jav∞ a jin²ch jazycφch. Nap°φklad v∞t╣ina nφzko·rov≥ov²ch (6) metod z Java Core API je nativnφch.
V b∞╛n²ch aplikacφch se nativnφ metody nepou╛φvajφ kv∙li jejich
nep°enositelosti. V appletech se pou╛φvat nesmφ.
- KlφΦovΘ slovo throws uvozuje jedno nebo vφce jmen t°φd v²jimek (viz kap. 13.), kterΘ m∙╛e metoda vyvolat. Je-li v²jimek vφce
jsou odd∞leny Φßrkami.
Priklad 11.12. |
Nßsledujφcφ metoda deklaruje, ╛e m∙╛e vyvolat v²jimky t°φdy ArithmeticException a SecurityException:
void metoda() throws ArithmeticException, SecurityException {
// ...
}
|
|
Zßrov∞≥ nelze pou╛φt dvojic static abstract a final abstract.
Argumenty metod se v╛dy p°edßvajφ hodnotou - hodnotu argumentu
sice m∞nit lze, ale navenek se to neprojevφ:
Priklad 11.13. |
Metoda prohod() mß zam∞nit hodnoty sv²ch dvou argument∙:
void prohod(int x, int y) {
int tmp = x; x = y; y = tmp;
}
void hop() {
int a = 1, b = 2;
prohod(a,b); // tohle nefunguje! (1)
// nadßle a = 1, b = 2
}
Po zavolßnφ metody prohod (1) se hodnoty argument∙ nezam∞nφ. Pro
sprßvnou funkci je t°eba provΘst tuto ·pravu: prom∞nnΘ x, y se
umφstφ do jednΘ instance t°φdy (2), na kterou se metod∞ prohod p°edß
reference (3):
class XY {
public int x, y; // (2)
}
void prohod(XY xy) {
int tmp = xy.x;
xy.x = xy.y;
xy.y = tmp;
}
void hop() {
XY xy = new XY(); // objekt xy namφsto a, b
xy.x = 1;
xy.y = 2;
prohod(xy); // (3)
// nynφ: xy.x = 2, xy.y = 1
}
|
|
11.2.3. Konstruktory
Konstruktor je specißlnφ metoda, kterß se volß pouze p°i vytvß°enφ
objektu (viz 11.1.1.) a slou╛φ k jeho inicializaci. JmΘno
konstruktoru musφ b²t shodnΘ se jmΘnem t°φdy, v nφ╛ je definovßn. Nßvratov²
typ konstruktoru se neuvßdφ.Pro konstruktory platφ pravidla uvedenß pro metody (viz 11.2.2.). Jejich
deklarace v╣ak nesmφ obsahovat modifikßtory abstract, final, native, static a synchronized a nedochßzφ k d∞d∞nφ konstruktor∙.
Priklad 11.14. |
class Bod {
Bod() { // konstrukor t°φdy Bod
// ...
}
}
|
|
Ka╛dß t°φda mß alespo≥ jeden konstruktor. Pokud ve t°φd∞ konstruktor nenφ
uveden, vytvo°φ p°ekladaΦ automaticky implicitnφ konstruktor bez
parametr∙ (default constructor), kter² nic neprovßdφ. Konstruktor ka╛dΘ t°φdy musφ na zaΦßtku obsahovat volßnφ konstruktoru
rodiΦovskΘ t°φdy, aby se zajistila °ßdnß inicializace zd∞d∞n²ch prom∞nn²ch
(tzv. °et∞zenφ konstruktor∙).
K volßnφ rodiΦovskΘho konstruktoru slou╛φ klφΦovΘ slovo super (viz tΘ╛
11.8.):
super( parametryKonstruktoru );
Volßnφ rodiΦovskΘho konstruktoru lze vynechat pouze v p°φpad∞, ╛e rodiΦovskß
t°φda mß pouze jeden konstruktor bez parametr∙ nebo konstruktor implicitnφ -
pak toto volßnφ p°ekladaΦ na zaΦßtek konstruktoru sßm doplnφ.
Volßnφ konstruktoru tΘ╛e t°φdy se provßdφ pomocφ operßtoru this (viz
tΘ╛ str. 11):
Priklad 11.15. |
class Trida {
public Trida() {
this(0); // volßnφ konstruktoru (*)
}
public Trida(int i) { // (*)
// ...
}
}
|
|
Pokud je pot°eba zabrßnit instanciovßnφ danΘ t°φdy, staΦφ nadefinovat v╣echny
jejφ konstruktory jako soukromΘ.
11.2.4. ╚lenskΘ prom∞nnΘ
╚lenskΘ prom∞nnΘ se deklarujφ v t∞le t°φdy - mimo t∞la metod (jinak
by se jednalo o lokßlnφ prom∞nnΘ). Podle konvence se deklarace Φlensk²ch
prom∞nn²ch uvßd∞jφ p°ed deklaracemi metod.Pro ΦlenskΘ prom∞nnΘ platφ podobnß pravidla jako pro lokßlnφ prom∞nnΘ (viz
9.4.). Jejich deklarace m∙╛e navφc obsahovat nßsledujφcφ modifikßtory:
[ prßva ] [static] [transient] [final] [volatile]
typ jmΘnoProm∞nnΘ
Priklad 11.17. |
Deklarace ve°ejnΘ celoΦφselnΘ statickΘ konstanty MAX_VALUE,
kterß je inicializovßna Φφslem 0x7fffffff (maximßlnφ hodnota pro typ
int) vypadß takto:
public static final int MAX_VALUE = 0x7fffffff;
|
|
11.3. D∞diΦnost
T°φda-potomek se od rodiΦovskΘ t°φdy odvodφ v deklaraci pomocφ klφΦovΘho slova
extends (viz 11.2.1.). Potomek od p°φmΘho rodiΦe d∞dφ, tj.
p°ejφmß jako by byly znovu definovßny, v╣echny ΦlenskΘ prom∞nnΘ a metody,
kterΘ: (8)
- jsou deklarovßny jako ve°ejnΘ (public) nebo chrßn∞nΘ (protected),
- nemajφ explicitn∞ urΦena p°φstupovß prßva a zßrove≥ se rodiΦovskß t°φda
nachßzφ ve stejnΘm balφku jako potomek.
Potomek ned∞dφ ΦlenskΘ prom∞nnΘ a metody, kterΘ:
- jsou deklarovßny jako soukromΘ (private) (9) ,
- jsou deklarovßny v jinΘm balφku a nejsou ve°ejnΘ (public),
- majφ v potomkovi stejnΘ jmΘno (a parametry - u metod) jako v rodiΦovskΘ
t°φd∞. Tyto ΦlenskΘ prom∞nnΘ (metody) jsou p°edefinovßny - tzv. p°ekrytφ prom∞nn²ch a metod (overriding).
P°i p°ekr²vßnφ metod je mo╛nΘ p°φstupovß prßva pouze roz╣φ°it (na public
nebo protected - v p°φpad∞ implicitnφch prßv). Naopak seznam (resp.
typy) v²jimek deklarovan²ch pomocφ throws lze pouze z·╛it. Na
zm∞ny modifikßtor∙ a ΦlenskΘ prom∞nnΘ omezenφ kladena nejsou. K p°ekryt²m metodßm a prom∞nn²m rodiΦe se p°istupuje pomocφ operßtoru super, kter² vracφ referenci na rodiΦovskou t°φdu:
super. JmΘno╚lenskΘProm∞nnΘ
super. JmΘnoMetody
Priklad 11.18. |
class A {
void a() {
// ...
}
}
class B extends A {
void a() {
super.a(); // volß metodu rodiΦe: A.a
a(); // volß sama sebe
// ...
}
}
|
|
11.4. P°φstupovß prßva
╚lenskΘ prom∞nnΘ a metody majφ specifikovßna p°φstupovß prßva (viz
kap. 11.2.2. a 11.2.4.) urΦujφcφ okruh t°φd, kterΘ k nim
majφ p°φstup. P°φstupem se rozumφ mo╛nost p°φmΘ manipulace se Φlensk²mi
prom∞nn²mi a volßnφ metod.
T°φda mß p°φstup pouze k metodßm a Φlensk²m prom∞nn²m, kterΘ:
- sama deklaruje,
- d∞dφ (viz 11.3.),
- jsou deklarovßny v jin²ch t°φdßch a jsou ve°ejnΘ (public),
- jsou umφst∞ny ve t°φd∞ stejnΘho balφku (viz kap. 12.)
a zßrove≥ majφ p°φstup nespecifikovßn nebo nastaven jako public Φi protected.
T°φda nemß p°φstup ke Φlensk²m prom∞nn²m a metodßm z jin²ch balφk∙, kterΘ jsou
soukromΘ, chrßn∞nΘ nebo majφ nespecifikovßn p°φstup.
Priklad 11.19. |
V p°φkladu 11.16. je konstanta MAX_VALUE deklarovßna jako
ve°ejnß a je tedy p°φmo p°φstupnß v╣em ostatnφm t°φdßm (i mimo sv∙j balφk).
|
|
11.5. T°φda Object
T°φda Object z balφku java.lang je ko°enovou t°φdou ve
stromu t°φd, tj. v╣echny t°φdy, a╗ u╛ knihovnφ nebo navr╛enΘ
programßtorem, majφ spoleΦnΘho (nep°φmΘho) rodiΦe t°φdu Object.
Object definuje zßkladnφ metody, kterΘ musφ mφt ka╛d² objekt v Jav∞ -
v∞t╣inu z nich pou╛φvß runtime systΘm. Jednß se nap°φklad o metody:
- protected native clone() - vytvo°φ identick² objekt (ale nevolß
konstruktor) a p°i°adφ stejnΘ hodnoty v╣em Φlensk²m
prom∞nn²m. (10) Funguje pouze u t°φd, kterΘ
implementujφ rozhranφ Cloneable.
- public boolean equals(Object obj) - porovnßvß objekt s objektem
obj.
- public final Class getClass() - vracφ objekt reprezentujφcφ
t°φdu v runtime systΘmu.
- public String toString() - vracφ identifikaΦnφ °et∞zec objektu,
- wait(), notify(), notifyAll() - viz
16.5.3..
11.6. Rozhranφ (interface)
Rozhranφ (interface) je syntaktickß struktura obsahujφcφ
deklarace konstant a metod (bez implementacφ). Deklarace rozhranφ je podobnß
deklaraci t°φdy:
[public] interface jmΘnoRozhranφ
[ extends seznamRozhranφ ] {
// t∞lo rozhranφ
}
T∞lo rozhranφ smφ obsahovat pouze deklarace konstant a metod. P°i
tom platφ nßsledujφcφ pravidla:
- V╣echny metody a konstanty uvedenΘ v deklaraci rozhranφ jsou automaticky
ve°ejnΘ (public) a nesmφ mφt specifikovßna p°φstupovß prßva
protected ani private.
- V╣echny metody jsou navφc automaticky abstraktnφ.
- I kdy╛ u prom∞nnΘ nenφ modifikßtor final, jednß se v╛dy
o konstantu.
- V rozhranφ nesmφ b²t pou╛ity modifikßtory: transient, volatile a synchronized.
Priklad 11.21. |
public interface NoveRozhranφ {
int MAX_DELKA_RETEZCE = 20; // automaticky konstanta
void vypis(String retezec); // automaticky abstraktnφ metoda
}
|
|
Rozhranφ se pou╛φvajφ k zachycenφ spoleΦn²ch prvk∙ t°φd, kterΘ spolu nemusφ
souviset ve stromu d∞diΦnosti - spoleΦn²mi prvky jsou konstanty a metody
deklarovanΘ rozhranφm. T°φda, kterß implementuje danΘ rozhranφ (viz
11.2.), musφ obsahovat definice v╣ech(!) metod tohoto rozhranφ. Rozhranφ
pak lze pou╛φt jako objektov² typ t°φdy:
Priklad 11.22. |
Program bude obsahovat schrßnku (clipboard), p°es kterou lze
kopφrovat, a vklßdat objekty (text, obrßzky, zvuky). V╣echny objekty, kterΘ
lze do schrßnky umφstit, musφ kopφrovßnφ samy umo╛≥ovat - musφ obsahovat
metodu copy(). Z hlediska nßvrhu nenφ vhodnΘ, aby t°φdy takto rozdφln²ch objekt∙ m∞ly
spoleΦnΘho rodiΦe - t°φdu, deklarujφcφ metodu copy(), kterou v╣echny
povinn∞ zd∞dφ. V²hodn∞j╣φ je deklarovat rozhranφ (Clip) obsahujφcφ
metodu copy(), kterΘ budou jednotlivΘ t°φdy implementovat - i v tomto
p°φpad∞ bude zaruΦena podpora kopφrovßnφ ze strany objekt∙.
public interface Clip {
byte[] copy();
}
Metoda copy() bude vracet pole byt∙ reprezentujφcφ objekt ve schrßnce.
Ka╛dß t°φda, jejφ╛ instance lze kopφrovat p°es schrßnku, musφ implementovat
rozhranφ Clip. Jejφ deklarace bude:
class Obrazek implements Clip {
byte[] copy() {
// ...
}
}
Schrßnka pak m∙╛e obsahovat libovoln² objekt typu Clip:
class Schranka {
byte[] schranka;
// metoda pro vlo╛enφ (kopφrovatelnΘho) objektu
public void vlozit(Clip objekt) { // typ parametru je rozhranφ
schranka = objekt.copy(); // vlo╛enφ objektu do schrßnky
}
// ...
}
|
|
Rozhranφ m∙╛e b²t prßzdnΘ. T°φdu implementujφcφ rozhranφ lze identifikovat
operßtorem instanceof, viz 8.2..
Rozhranφ neumo╛≥ujφ vφcenßsobnou d∞diΦnost, nebo╗ t°φdy prost°ednictvφm
rozhranφ ned∞dφ definice (k≤d) metod. Hierarchie rozhranφ je nezßvislß na
hierarchii t°φd.
11.7. Inicializace t°φd a rozhranφ
K inicializaci t°φdy nebo rozhranφ dochßzφ p°i prvnφm aktivnφm
pou╛itφ, kterΘ nastane, je-li spln∞na aspo≥ jedna
z podmφnek (11) :
- je vyvolßna metoda nebo konstruktor deklarovan² danou t°φdou.
- je vytvo°eno pole s prvky typu danΘ t°φdy,
- je proveden p°φstup k nekonstantnφ ΦlenskΘ prom∞nnΘ t°φdy nebo konstant∞
rozhranφ,
- je proveden p°φstup ke ΦlenskΘ prom∞nnΘ t°φdy s modifikßtorem final
nebo static, kterß je inicializovßna hodnotou vypoΦφtanou za b∞hu programu.
Inicializace t°φdy se sklßdß z inicializace statick²ch Φlensk²ch prom∞nn²ch a
vykonßnφ statick²ch inicializßtor∙ (viz dßle), p°iΦem╛ p°ed tφm musφ
b²t inicializovßna nejprve jejφ rodiΦovskß t°φda. Inicializace rozhranφ spoΦφvß pouze v inicializaci v n∞m definovan²ch
konstant, nedochßzφ automaticky k inicializaci rodiΦovskΘho rozhranφ.
11.7.1. Inicalizßtory
Od JDK 1.1 lze k inicializaci t°φdy (resp. instance) pou╛φt statick² (resp.
nestatick²) inicializßtor. Jeho syntaxe je:
deklaraceT°φdy {
[static] {
// inicializace
}
}
Jednß se o blok, kter² obsahuje inicializace Φlensk²ch prom∞nn²ch. Statick²
inicializßtor vyvolßvß pouze t°φda. Nestatick² inicializßtor vyvolßvajφ
v╣echny konstruktory t°φdy. Nestatick² inicializßtor smφ vyvolßvat pouze
v²jimky, kterΘ deklarujφ v╣echny konstruktory t°φdy. (12) .
Priklad 11.23. |
class A {
static {
String ahoj = "ahoj";
}
// ...
}
|
|
11.8. Vno°enΘ t°φdy
Od verze JDK 1.1 je mo╛nΘ t°φdy do sebe vno°ovat (13) a Java rozeznßvß dva druhy t°φd:
- T°φdy nejvy╣╣φ ·rovn∞ (top-level classes) - jsou
"normßlnφ" t°φdy a statickΘ t°φdy (14) umφst∞nΘ v jinΘ t°φd∞ (na ·rovni vno°enφ nezßle╛φ). Do tΘto skupiny
se takΘ °adφ takΘ vno°enß rozhranφ.
Priklad 11.24. |
Ob∞ nßsledujφcφ t°φdy TopLevel1 a TopLevel2 jsou t°φdy nejvy╣╣φ
·rovn∞.
class TopLevel1 {
static class TopLevel2 {
// ...
}
interface Cool {
// i rozhranφ m∙╛e b²t vno°enΘ
}
}
|
|
T°φdy nejvy╣╣φ ·rovn∞ mohou b²t zp°φstupn∞ny (zßvisφ na p°φstupov²ch prßvech)
udßnφm ·plnΘho jmΘna t°φdy. Podobn∞ jako u balφk∙ (viz kap.
12.) se pou╛φvß teΦkovß notace: TopLevel1.TopLevel2 je ·plnΘ
jmΘno vno°enΘ t°φdy TopLevel2. T°φdy nejvy╣╣φ ·rovn∞ umo╛≥ujφ vytvß°et hierarchickou strukturu na ·rovni
t°φd, nikoliv pouze na ·rovni balφk∙.
- Vnit°nφ t°φdy (inner classes) - jsou nestatickΘ vno°enΘ t°φdy a lze je umφstit i do t∞la metody nebo do bloku.
Vnit°nφ t°φdy definovanΘ v bloku nebo metod∞ nejsou "zvenku" p°φstupnΘ
a nemohou mφt modifikßtory public, protected, private
a static. Vnit°nφ t°φdy nesmφ obsahovat statickΘ prom∞nnΘ a metody,
statickΘ inicializßtory, ani deklarace rozhranφ.
Vnit°nφ t°φdy jsou obecn∞j╣φm nßstrojem pro p°φpady, kdy jinΘ jazyky pou╛φvajφ
ukazatele na funkce. Zvlß╣tnφm druhem vnit°nφ t°φdy je nepojmenovanß, anonymnφ
t°φda (anonymous class). Deklarace anonymnφ t°φdy je souΦßstφ
roz╣φ°enΘ syntaxe operßtoru new:
new Typ ( parametry ) {
// t∞lo anonymnφ t°φdy
}
Typ p°edstavuje:
- jmΘno konstruktoru rodiΦovskΘ(!) t°φdy, od kterΘ je anonymnφ t°φda
odvozena (nßsledujφ jeho parametry), nebo
- jmΘno rozhranφ - anonymnφ t°φda jako jedinß m∙╛e p°φmo instanciovat
rozhranφ (zde se parametry neuvßdφ). (15)
Priklad 11.25. |
Vytvo°enφ ΦlenskΘ prom∞nnΘ r jako instance rozhranφ Runnable (viz
tΘ╛ 16.2.) vypadß nßsledovn∞:
class NejakaTrida {
Runnable r = new Runnable() {
public void run() {
// ...
}
}
}
|
|
Vnit°nφ t°φdy majφ p°φm² p°φstup k soukrom²m statick²m prom∞nn²m a metodßm
vn∞j╣φ t°φdy a nemusφ pou╛φvat jejich ·plnß jmΘna. T°φdy nejvy╣╣φ
·rovn∞ mohou manipulovat pouze se statick²mi prom∞nn²mi a statick²mi metodami
vn∞j╣φch t°φd. Pokud vnit°nφ t°φda ve sv²ch metodßch pou╛φvß lokßlnφ prom∞nnΘ nebo parametry,
kterΘ sama nedeklaruje, musφ tyto b²t deklarovßny s modifikßtorem final.
Proto╛e po zavedenφ vnit°nφch t°φd v JDK 1.1 m∙╛e mφt danß t°φda vφce instancφ,
je v n∞kter²ch p°φpadech pou╛itφ operßtor∙ new a super nutno
explicitn∞ uvΘst referenci na instanci vn∞j╣φ t°φdy: (16)
referenceNaVn∞j╣φInstanci. new
referenceNaVn∞j╣φInstanci. super
Podobn∞ byla roz╣φ°ena syntaxe operßtoru this, kde je mo╛nΘ specifikovat
vn∞j╣φ t°φdu:
JmΘnoVn∞j╣φT°φdy. this
Priklad 11.26. |
class Vnejsi {
static int i = 10; // (1)
int x;
class Vnitrni {
Vnitrni() {
int i = 0; // (2)
int j = Vnejsi.this.i; // (3)
// ...
}
}
static Vnitrni delej(Vnejsi obj) {
// ...
return obj.new Vnitrni(); // (4)
}
}
Na °ßdce (3) je prom∞nnΘ j p°i°azen obsah statickΘ prom∞nnΘ i
(1) - v p°φpad∞ neuvedenφ t°φdy by se p°i°adila hodnota prom∞nnΘ i (2). Na °ßdce (4) je nutnΘ u operßtoru new uvΘst referenci na instanci
obj, nebo╗ metoda delej() je statickß a jako takovß nem∙╛e
(automaticky) p°edat konstruktoru referenci na instanci vn∞j╣φ t°φdy.
|
|
|