1 4. T!ídy a objekty Pojetí pojmu objekt se v r!zn"ch programovacích jazycích li#í. V tomto textu budeme vycházet z p$edstavy, kterou zavedl SmallTalk...
Pojetí pojmu objekt se v r!zn"ch programovacích jazycích li#í. V tomto textu budeme vycházet z p$edstavy, kterou zavedl SmallTalk a která je dodnes v objektov"ch jazycích více %i mén& dodr'ována. Objekt je ucelen" souhrn dat (abstraktní datová struktura), kter" je charakterizován t$emi základními vlastnostmi: zapouzd$ením, polymorfismem a d&di%ností. T&mito pojmy se budeme zab"vat v následujících %ástech, nyní uvedeme pouze základní definice. Ka'd" objekt obsahuje krom& sv"ch dat i kód, kter" s t&mito daty pracuje. Tomuto kódu se $íká metody. Metoda je zvlá#tní druh funkce, která se spustí, kdykoliv chce u'ivatel vykonat s objektem n&jakou akci. Ka'd" objekt m!'e obsahovat více metod, podle toho, jaké akce s ním lze provád&t. Spou#t&ní metod se d&je pomocí mechanismu zasílání zpráv. Ka'dá metoda objektu má své jméno; pokud chceme n&jakou metodu zavolat, po#leme objektu zprávu tého' jména. Pokud tedy za#leme objektu zprávu A, systém mezi jeho metodami nalezne metodu A a spustí ji. Této metod& se $íká obsluha zprávy A, procesu zavolání obsluhy dané zprávy se $íká její obslou!ení. Zpráva zasílaná objektu m!'e obsahovat argumenty podobn&, jako m!'e argumenty obsahovat volání funkce. Obsluha zprávy (metoda) má pak tyto argumenty k dispozici (podobn& jako funkce). Obsluha zprávy také m!'e vracet hodnotu jako sv!j v"sledek. Poznámka 4.1. V Common Lispu je na rozdíl od této u'#í definice zvykem naz"vat objektem jakákoli data. V p$ípad&, 'e by mohlo dojít k nedorozum&ní, je tedy n&kdy t$eba blí'e specifikovat, v jakém smyslu zrovna o objektech hovo$íme. Proto budeme n&kdy pou'ívat zp$es(ující termíny, jako objekt Common Lispu (lispov" objekt), objekt ve smyslu objektového programování a podobn&. Poznámka 4.2. Ka'dé zaslání zprávy, které zm&ní vnit$ní stav objektu, znamená vedlej#í efekt. V samém srdci objektového programování tak stojí princip vedlej#ího efektu, kter" je v p$ímém rozporu se zásadami funkcionálního programování.
4.1.
T!ídy
Data v objektech jsou (podobn& jako u struktur v jazyce C) rozd&lena do jednotliv"ch pojmenovan"ch polo'ek. V Common Lispu se t&mto polo'kám $íká sloty. Ka'd" slot objektu má své (v rámci objektu) jedine%né jméno. T#ída je, ve své jednodu##í podob&, popis objektu. Obsahuje jednak seznam názv! slot! objektu a jednak definici v#ech jeho metod. P$i b&hu programu slou'í t$ída jako p$edloha k vytvá$ení nov"ch objekt!. Objekt, jeho' popisem je daná t$ída, se naz"vá p#ímou instancí této t$ídy. Poznámka 4.3. Uvedenou definici t$ídy v následujících kapitolách je#t& roz#í$íme. Mimo jiné definujeme pojem instance t$ídy, kter" je obecn&j#í ne' pojem p$ímé instance. Pokud v následujícím textu pou'ijeme pojem instance, vztahuje se to k tomuto obecn&j#ímu pojmu (a tedy i k pojmu p$ímé instance).
Pr˚ uvodce studiem Zopakujme si, v %em jsou shodné a v %em se mohou li#it dv& p$ímé instance té'e t$ídy: 1. Dv& p$ímé instance té'e t$ídy obsahují stejnou sadu slot!, tedy mají stejn" po%et slot! stejn"ch názv!. Hodnoty t&chto slot! v#ak mohou b"t r!zné. 2. Dv& p$ímé instance té'e t$ídy obsahují stejné metody.
T$ída je datov" typ. Ve staticky typovan"ch programovacích jazycích lze t$ídy pou'ívat ke specifikaci typ! prom&nn"ch, v dynamicky typovan"ch programovacích jazycích pak lze na t$ídy pou'ít nástroje k dynamickému zji#)ování typu dat (v Common Lispu nap$íklad funkci typep). Tyto mo'nosti jsou ov#em k dispozici i ve staticky typovan"ch jazycích (konstrukce “is“), do kter"ch tak objektové programování vná#í prvky dynamického typování.
4.2.
T!ídy a instance v Common Lispu
Podívejme se, jak jsou obecné pojmy z p$edchozích podkapitol realizovány v Common Lispu. Nové t$ídy se definují pomocí makra defclass, které specifikuje seznam slot! t$ídy, a pomocí makra defmethod, které slou'í k definici metod instancí t$ídy. Nové objekty se vytvá$ejí pomocí funkce make-instance. Ke %tení hodnoty slotu objektu slou'í funkce s názvem slot-value, kter" lze v kombinaci s v"razem setf pou'ít i k nastavování hodnot slot!. Zprávy se v Common Lispu objekt!m zasílají pomocí stejné syntaxe, jakou se v tomto jazyce volají funkce. Zjednodu#ená syntax makra defclass je následující: (defclass name () slots)
Definice t#ídy: makro defclass, 1. verze
name: symbol (nevyhodnocuje se) slots: seznam symbol! (nevyhodnocuje se) Symbol name je název nov& definované t$ídy, symboly ze seznamu slots jsou názvy slot! této t$ídy. Poznámka 4.4. Prázdn" seznam za symbolem name je sou%ástí zjednodu#ené syntaxe. V dal#ích kapitolách, a' se dozvíme více o t$ídách, uká'eme, co lze pou'ít místo n&j.
P!íklad 4.5. Definice t$ídy point, její' instance by obsahovaly dva sloty s názvy x a y by vypadala takto: (defclass point () (x y))
Definovali-li jsme novou t$ídu (zatím pouze t$ídu bez metod, k jejich' definici se dostaneme vzáp&tí), m&li bychom se nau%it vytvá$et její p$ímé instance. V Common Lispu k tomu pou'íváme funkci make-instance, její' zjednodu#ená syntax je tato: (make-instance class-name)
class-name: symbol Funkce make-instance vytvo$í a vrátí novou p$ímou instanci t$ídy, její' jméno najde ve svém prvním parametru. V#echny sloty nov& vytvo$eného objektu jsou neinicializované a ka'd" pokus získat jejich hodnotu skon%í chybou (pozd&ji si $ekneme, jak se získávají hodnoty slot! a pak to budeme moci vyzkou#et). P!íklad 4.6. Pokud jsme definovali t$ídu point tak, jak je uvedeno v p$edchozím p$íklad&, m!'eme nyní vyzkou#et vytvo$ení její instance:
Vytvá#ení instancí: funkce make-instance
CL-USER 2 > (make-instance 'point) #
Pr˚ uvodce studiem Pokud není v tento moment %tená$i jasné, pro% jsme ve v"razu (make-instance 'point) symbol point kvotovali, m&l by si uv&domit, 'e make-instance je funkce a zopakovat si základy vyhodnocovacího procesu v Common Lispu.
V"sledek volání není p$íli# %iteln", v prost$edí LispWorks si jej ale m!'eme prohlédnout v inspektoru. Pokud v Listeneru klikneme na tla%ítko s mikroskopem ( ), objeví se okno obsahující údaje o posledním v"sledku, jak je vid&t na Obrázku 4.
Obr´ azek 4: Neinicializovaná instance t$ídy point v inspektoru Text # u názv! jednotliv"ch slot! znamená, 'e sloty jsou neinicializované. M!'eme jim ale pomocí prost$edí LispWorks zkusit nastavit hodnotu. Kliknemeli na n&kter" ze zobrazen"ch slot! prav"m tla%ítkem, m!'eme si v objeviv#í se nabídce vybrat volbu “Slots->Set…” tak, jak je znázorn&no na Obrázku 5 a novou hodnotu slotu nastavit. K programovému %tení hodnot slot! slou'í funkce slot-value, k jejich nastavování symbol slot-value v kombinaci s makrem setf. Syntax je následující:
$tení a nastavování slot%: slot-value
(slot-value object slot-name)
object: objekt slot-name: symbol P!íklad 4.7 (práce s funkcí slot-value). Vyzkou#ejme si práci s funkcí slot-value. Nejprve vytvo$me instanci ji' definované t$ídy point a ulo'me ji do prom&nné pt: CL-USER 2 > (setf pt (make-instance 'point)) #
Obr´ azek 5: Nastavování hodnoty slotu v inspektoru
Pr˚ uvodce studiem Pou'ití prom&nné, kterou jsme d$íve nedefinovali (jako v tomto p$ípad& prom&nné pt), je povoleno pouze k experimentálním ú%el!m v p$íkazovém $ádku. Na jin"ch místech je v"vojové prost$edí nepovoluje. Ka'dou prom&nnou je t$eba bu* definovat jako lexikální (nap$íklad pomocí speciálního operátoru let), nebo jako dynamickou (makrem defvar). Nyní zkusme získat hodnotu slotu x nov& vytvo$ené instance: CL-USER 3 > (slot-value pt 'x) Error: The slot X is unbound in the object # (an instance of class #<STANDARD-CLASS POINT 200972AB>). 1 (continue) Try reading slot X again. 2 Specify a value to use this time for slot X. 3 Specify a value to set slot X to. 4 (abort) Return to level 0. 5 Return to top loop level 0. Type :b for backtrace, :c