10. Zßkladnφ pojmy z OOP
Tato kapitola je urΦena t∞m, kte°φ nemajφ zku╣enosti se ╛ßdn²m objektov²m
jazykem a struΦn∞ vysv∞tluje zßkladnφ pojmy z objektov∞ orientovanΘho
programovßnφ (OOP). Ostatnφm postaΦφ, kdy╛ se seznßmφ
s kap. 10.5..
10.1. Objekt
Ka╛d² v∞t╣φ program se sklßdß z n∞kolika modul∙ - jeden se starß o v²stup na
obrazovku a zpracovßvß pokyny od u╛ivatele, dal╣φ provßdφ v²poΦty, je╣t∞ jin²
posφlß data po sφti atd. Ka╛d² tento modul je naprogramovßn do znaΦnΘ mφry
samostatn∞, nejen proto, aby se v n∞m autor po p∙l roce sßm vyznal, ale
zejmΘna se ji╛ hotovΘ (a odlad∞nΘ!) moduly dajφ pou╛φt v dal╣φch programech.
Priklad 10.1. |
Modulem m∙╛e b²t nap°φklad standardnφ knihovna pro prßci se soubory,
kterß obsahuje funkce pro otev°enφ, Φtenφ, zßpis do souboru atd. V Turbo Pascalu a jazyce C je tato knihovna realizovßna tak, ╛e ·daje
o fyzickΘm souboru (pozice pro Φtenφ a zßpis, odkaz na v vyrovnßvacφ pam∞╗
atd.) jsou ulo╛eny v datovΘ struktu°e - prom∞nnΘ typu soubor (FILE).
Tato prom∞nnß se v programu pou╛φvß jako argument p°i volßnφ funkcφ knihovny. Nev²hodou ov╣em je, ╛e s obsahem struktury zmφn∞nΘ prom∞nnΘ mohou manipulovat
krom∞ knihovny, kterΘ to p°φslu╣φ, i jinΘ Φßsti programu a v p°φpad∞ p°epsßnφ
·daj∙ m∙╛e pozd∞ji dojφt k jeho zhroucenφ apod. BezpeΦn∞j╣φ by bylo, kdyby
k ·daj∙m tΘto prom∞nnΘ m∞ly p°φstup v²hradn∞ funkce p°φslu╣nΘ knihovny.
╪e╣enφm je uzav°φt ·daje spolu s p°φslu╣n²mi funkcemi do jednoho
modulu a mφsto datovΘ struktury pou╛φt pouze odkaz (referenci). OOP jde v tomto sm∞ru je╣t∞ dßle a s ka╛d²m souborem (resp. s daty o souboru)
p°φmo svß╛e funkce, kterΘ s nφm mohou v²luΦn∞ manipulovat. V╣e si lze
p°edstavit nßsledovn∞: ![objekt.gif](/file/23392/Chip_2000-10_cd1.bin/chplus/Java/images/objekt.gif)
|
|
Objekt je runtime entita (1) sklßdajφcφ se
z prom∞nn²ch, zvan²ch ΦlenskΘ prom∞nnΘ (member variables), a
p°φslu╣ejφcφch funkcφ, zvan²ch metody (methods). V Φlensk²ch
prom∞nn²ch je obsa╛en stav objektu, tj. v╣e, co si objekt
"pamatuje", a metody vyjad°ujφ jeho chovßnφ, tedy v╣e, co objekt
"umφ".
Priklad 10.2. |
My╣lenka objekt∙ byla p°evzata z reßlnΘho sv∞ta. Jednφm
z nejjednodu╣╣φch reßln²ch objekt∙ je obyΦejn² vypφnaΦ - jeho stavem
je: poloha (vypnuto, zapnuto) a chovßnφm: zapnutφ a vypnutφ. I zde je v╣e
uzav°eno uvnit° a nemßme mo╛nost p°φmo (bez ╣roubovßku) manipulovat
se stavem vypφnaΦe a p°ivodit si ·raz.
|
|
Uzav°enost (encapsulation) je jednou z nejd∙le╛it∞j╣φch
vlastnostφ objekt∙ a mß krom∞ bezpeΦnosti je╣t∞ v²hodu skrytφ vnit°nφ
implementace a modularity - softwarov² objekt m∙╛e b²t p°i zachovßnφ
rozhranφ metod uvnit° zcela p°eprogramovßn a m∙╛e se libovoln∞ m∞nit vnit°nφ
struktura dat (Φlensk²ch prom∞nn²ch), ale nenφ t°eba p°izp∙sobovat okolφ.
V programech se uzav°enost ·pln∞ striktn∞ nedodr╛uje - nap°φklad pokud objekt
reprezentuje pouze datovou strukturu (nemß metody), nebo z d∙vodu rychlosti -
a je mo╛nΘ povolit p°φm² p°φstup k libovoln²m Φlensk²m prom∞nn²m (viz
11.4.). To by se v╣ak m∞lo t²kat pouze t∞ch prom∞nn²ch,
jejich╛ zm∞nou zvenΦφ nelze uvΘst objekt do nekonzistentnφho
("nesmyslnΘho") stavu - nap°. u souboru nastavenφ pozice pro Φtenφ na
zßpornou hodnotu.
Jeden objekt se samoz°ejm∞ m∙╛e obsahovat dal╣φ, v╣e zßle╛φ na zvolenΘ
rozli╣ovacφ schopnosti. Nap°φklad pro n∞kterΘ aplikace lze poΦφtaΦ
reprezentovat jednφm objektem, pro jinΘ se bude sklßdat z dal╣φch
(motherboardu, harddisku, videokarty, °adiΦe atd.).
10.2. Zprßva
SamotnΘ objekty vyd∞lenΘ ze sv∞ta by byly k niΦemu, a proto spolu komunikujφ
pomocφ tzv. zasφlßnφ zprßv.Zprßva je obecn² pojem, jφm╛ se oznaΦuje zaslßnφ po╛adavku mezi
objekty bez ohledu na zp∙sob p°enosu, (2) jeho╛
v²sledkem je volßnφ metody cφlovΘho objektu. Zprßvu obecn∞ tvo°φ:
- jmΘno objektu, kterΘmu je obsah urΦen,
- jmΘno metody, kterß se mß vykonat,
- parametry metody (data).
Mechanismus zasφlßnφ zprßv tak umo╛≥uje, ╛e se komunikujφcφ softwarovΘ objekty
mohou nalΘzat ve dvou r∙zn²ch procesech, programech nebo dokonce na dvou
r∙zn²ch poΦφtaΦφch. Pro jednotlivΘ situace v╣ak nenφ t°eba objekty
p°izp∙sobovat.
10.3. T°φda
V∞t╣ina podstatn²ch jmen v na╣em jazyce oznaΦuje t°φdu ╛iv²ch,
ne╛iv²ch nebo abstraktnφch objekt∙. Nap°φklad va╣e ╣kodovka a soused∙v
Mercedes jsou objekty pat°φcφ do t°φdy aut. T°φdou se v podstat∞ rozumφ obecnΘ
vlastnosti, kterΘ objekt musφ mφt, aby do nφ mohl b²t za°azen - neboli: t°φda
je popisem, vzorem, p°edlohou celΘ skupiny podobn²ch objekt∙.V programovacφm jazyce je t°φda (class (3) ) p°esn∞ popsßna. Z hlediska
syntaxe je t°φda obyΦejnou deklaracφ datovΘ struktury (podobn∞ jako
record v Pascalu nebo struct v C) roz╣φ°enou o metody. T°φda
p°edstavuje objektov² typ, objekt se naz²vß instancφ
t°φdy.
Priklad 10.3. |
Realizace vypφnaΦe z p°φkladu 10.2. v Jav∞ m∙╛e vypadat takto:
public class Vypinac {
private boolean poloha = false;
public void zapni() {
poloha = true;
}
public void vypni() {
poloha = false;
}
public void vypisStav() {
if (poloha)
System.out.println("Zapnuto.");
else System.out.println("Vypnuto.");
}
}
T°φda Vypinac obsahuje ve°ejn∞ p°φstupnΘ (public) metody zapni() a vypni() a soukromou (private) Φlenskou prom∞nnou poloha. Podle tΘto t°φdy m∙╛e program vytvo°it teoreticky libovolnΘ mno╛stvφ
nezßvisl²ch instancφ:
public class Program {
public static void main(String[] args) {
Vypinac prvni = new Vypinac(); // vytvo°enφ vypφnaΦe
Vypinac druhy = new Vypinac(); // vytvo°enφ vypφnaΦe
prvni.zapni();
prvni.vypisStav();
druhy.vypisStav();
}
}
|
|
Dosud v╣e nasv∞dΦuje tomu, ╛e t°φda je pouhou deklaracφ objekt∙ a v programu
fyzicky neexistuje - existujφ a╛ jejφ konkrΘtnφ objekty, kterΘ majφ sv∙j stav
ulo╛en v Φlensk²ch prom∞nn²ch. I samotnß t°φda v╣ak m∙╛e mφt prom∞nnΘ (class variables) a metody (class methods), naz²vanΘ tΘ╛ statickΘ. StatickΘ prom∞nnΘ existujφ jen v jednom exemplß°i
a v╣echny objekty danΘ t°φdy je sdφlφ - jsou tedy jakousi obdobou
globßlnφch prom∞nn²ch pro danou t°φdu. StatickΘ metody (4) majφ tu v²hodu, ╛e je lze volat, i kdy╛
(je╣t∞) neexistuje ╛ßdnß instance t°φdy - viz metoda main v p°φkladu
4.2..
10.4. D∞diΦnost
Jedna t°φda obvykle nestaΦφ pro dostateΦn∞ p°esnou klasifikaci podobn²ch
objekt∙, nap°φklad do t°φdy aut pat°φ dodßvky, nßkladnφ, osobnφ auta atd.
P°itom podt°φdy majφ vlastnosti t°φdy nad°azenΘ. Tuto my╣lenku p°evzalo i OOP.ObjektovΘ jazyky umo╛≥ujφ konstruovat t°φdy tak, ╛e od prvnφ (nejobecn∞j╣φ)
se mohou odvozovat dal╣φ p°idßnφm nebo p°ekrytφm (p°edefinovßnφm)
metod (a p°φp. p°idßnφm prom∞nn²ch). Toto odvozovßnφ je mo╛nΘ dßle opakovat a
v²slednΘ t°φdy jsou pak uspo°ßdßny do stromovΘ hierarchie: ![strom.gif](/file/23392/Chip_2000-10_cd1.bin/chplus/Java/images/strom.gif) Nßslednφk danΘ t°φdy ve stromu se naz²vß potomek (subclass)
a p°edch∙dce rodiΦ (superclass), podobn∞ jako v rodokmenu. T°φda v danΘm uzlu s v²jimkou ko°ene d∞dφ (tj. p°ejφmß, jako by byly
znovu definovßny) v╣echny prom∞nnΘ a metody rodiΦe (5) a tφm,
nep°φmo, i v╣ech nad°azen²ch t°φd. P°i prochßzenφ stromu shora dol∙ tak
zφskßvßme Φφm dßl specializovan∞j╣φ t°φdy. Dφky d∞diΦnosti se p°i programovßnφ lze vyhnout mnoh²m chybßm (odvozenß
t°φda pou╛φvß ji╛ odlad∞n² k≤d z rodiΦe) a u╣et°φ se i op∞tovnΘ psanφ k≤du
(metody rodiΦovskΘ t°φdy nenφ t°eba znovu definovat).
Na rozdφl od n∞kter²ch jin²ch jazyk∙ (nap°. C++) Java nepodporuje tzv.
vφcenßsobnou d∞diΦnost, kdy m∙╛e t°φda mφt vφce ne╛ jednoho rodiΦe,
nebo╗ to obvykle p°inß╣φ v∞t╣φ obtφ╛e ne╛ v²hody (nap°. nar∙stß komplexnost
zdrojovΘho textu). P°φpad, kdy by t°φda m∞la mφt vlastnosti vφce rodiΦ∙, Java
obchßzφ pomocφ rozhranφ (interface), viz 11.6..
V Jav∞ jsou v╣echny t°φdy uspo°ßdßny do jedinΘho stromu, jeho╛ ko°enem
je t°φda Object (viz 11.5.). Pokud v programu nenφ uveden
rodiΦ novΘ t°φdy, je jφm automaticky prßv∞ Object. (6)
10.5. Vφcetvarost
V p°edchozφ kapitole bylo naznaΦeno, ╛e pokud danß t°φda d∞dφ metody rodiΦe,
jsou tyto p°ejaty a chovajφ se jako by byly v tΘto t°φd∞ znovu definovßny.To v podstat∞ vyjad°uje vφcetvarost (polymorphism), kterß
°φkß, ╛e jmΘno akce (metody) je sdφleno t°φdami ve stromu d∞diΦnosti a ta je
implementovßna zp∙sobem, kter² ji na danΘ ·rovni p°φslu╣φ. Stoprocentn∞ to ov╣em platφ pouze o Jav∞, nikoliv nap°φklad o Turbo
Pascalu Φi C++. V praxi jde o to, jak se ve zd∞d∞n²ch metodßch volajφ p°ekrytΘ
(p°edefinovanΘ) metody potomk∙:
Priklad 10.4. |
Mßme t°φdu Bod, jejφ╛ instance p°edstavujφ body na obrazovce.
T°φda Bod obsahuje dv∞ metody:
- zobraz() - zobrazφ bod na aktußlnφch sou°adnicφch,
- posun() - p°esune bod o zadan² ·sek (zm∞nφ jeho sou°adnice) a
nßsledn∞ zavolß metodu zobraz().
T°φda Kruh je potomkem t°φdy Bod, d∞dφ tedy ob∞ uvedenΘ metody.
Metoda zobraz() je v╣ak ve t°φd∞ Kruh p°ekryta - zobrazφ kruh. P°i volßnφ metod pak v Jav∞ dostaneme v²sledek, kter²
bychom asi oΦekßvali:
- metoda posun() t°φdy Bod zm∞nφ sou°adnice a zobrazφ bod,
- metoda posun() t°φdy Kruh zm∞nφ sou°adnice a zobrazφ kruh.
V C++ Φi Turbo Pascalu dopadne v²stup "kupodivu" takto:
- metoda posun() t°φdy Bod zm∞nφ sou°adnice a zobrazφ bod,
- metoda posun() t°φdy Kruh zm∞nφ sou°adnice a zobrazφ bod!
V programu je toti╛ k≤d metody posun() obou t°φd sdφlen a
instance obou t°φd tedy pou╛φvajφ fyzicky tutΘ╛ metodu. V C++ je
v metod∞ posun() "napevno" p°elo╛eno volßnφ metody zobraz() (7) - t°φdy Bod, a proto dojde k uvedenΘmu
v²sledku. Oproti tomu v Jav∞ se v metod∞ posun() a╛ za
b∞hu programu rozhoduje, kterß z metod zobraz() se bude
volat (8) . JmΘno metody posun() je (v p°φpad∞ Javy) sdφleno ob∞ma t°φdami a ta
funguje zp∙sobem, kter² ji na danΘ ·rovni p°φslu╣φ (vφcetvarost).
|
|
V C++ Φi Turbo Pascalu lze dosßhnout stejnΘho v²sledku jako v Jav∞ tφm, ╛e
je metoda (zobraz()) deklarovßna jako virtußlnφ. Pak se jejφ
volßnφ provßdφ nep°φmo p°es tzv. tabulku virtußlnφch metod. Z pohledu
C++ jsou tedy v╣echny nestatickΘ metody v Jav∞ virtußlnφ.
|