Skip to main content

Cocoa (Ukázka, strana 99)

Page 1

98

COCOA – ÚVOD DO PROGRAMOVÁNÍ NA PLATFORMĚ APPLE plicitně uvádět – nebo jméno atributu s prefixem „is“. V knihovnách Cocoa se sice výjimečně můžeme setkat i s prefixem „has“ (hasAlpha); to však má historické důvody a sami bychom takové atributy definovat spíše neměli.

5.6.3 Přístup k atributům s využitím tečkové konvence Z minulého bodu je zřejmé, že kdykoli a bez omezení můžeme pracovat s atributy instancí pomocí přístupových metod, popsaných v minulém bodu: MyClass *o=...; ... if ([o isEnabled]) [o setEnabled:NO]; [o setCount:[o count]+1]; ... Objective C 2.0 navíc přináší možnost k atributům přistupovat pomocí tečkové notace, jež je z pohledu programátora o něco pohodlnější – název atributu prostě od proměnné (resp. obecně výrazu, jehož hodnotou je ukazatel na objekt) oddělíme tečkou, a výsledek se může účastnit běžných výrazů jazyka C. Výše uvedený příklad bychom tedy mohli přepsat takto: MyClass *o=...; ... if (o.isEnabled) o.enabled=NO; o.count++; ... Povšimněme si zvláště velmi podstatného zjednodušení druhého z příkladů (inkrementace atributu count). Důležité je mít ale na paměti, že ačkoli se tento zápis na první pohled značně podobá přímému přístupu k instančním proměnným např. v Javě, jde o podobnost jen náhodnou, a Objective C i při tečkové notaci zachovává plně objektový přístup prostřednictvím zpráv a přístupových metod (takže např. zápis „o.count++“ nejprve pošle objektu o zprávu count, inkrementuje zjištěnou hodnotu, a výsledek zapíše zpět do objektu o pomocí zprávy setCount:). Ve starších verzích překladače než Objective C 2.0 ještě nebyla tečková konvence k dispozici. Programujeme-li pro takovéto prostředí, musíme tedy důsledně všude používat přístupových metod explicitně, jako v prvém příkladu tohoto bodu.

5.7 Metody tříd Připomeňme, že třída sama je objektem, a sama tedy dokáže přijímat a zpracovávat zprávy. Proto můžeme v rozhraní kromě deklarace zpráv určených pro instance této třídy deklarovat i zprávy určené pro třídu samotnou. Podobně v implementaci můžeme definovat „třídní“ metody – tedy takové, jež budou vyvolány v případě, že třída sama dostane zprávu, odpovídající hlavičce metody. V obou případech je deklarace i definice takřka stejná jako tomu bylo v případě instancí; jen znak „-“ na začátku deklarace zprávy či definice metody je nahrazen znakem „+“:

5. Objekty a Objective C

Ukázka elektronické knihy, UID: KOS180655


COCOA – ÚVOD DO PROGRAMOVÁNÍ NA PLATFORMĚ APPLE

99

@interface MyClass:NSObject +(NSString*)name; // pro samotnou třídu -(NSString*)name; // pro její instance @end @implementation MyClass +(NSString*)name { return @"třída MyClass"; } -(NSString*)name { return @"instance třídy MyClass"; } @end Interpretace zpráv a vyhledání odpovídajících metod zde funguje přesně stejně, jako tomu bylo v případě instance: dostane-li třída sama nějakou zprávu, pokusí se nalézt svou „plusovou“ metodu, jejíž jméno odpovídá jménu přijaté zprávy. Nalezne-li ji, provede její kód; jinak hledá odpovídající metodu v nadtřídě, a v její nadtřídě... až po kořenovou třídu. Nenalezne-li ji ani tam (a není-li v žádné z nich implementováno ani dynamické zpracování libovolné zprávy), ohlásí se chyba. V metodách třídy můžeme samozřejmě využívat bez omezení i proměnné self – jež zde bude obsahovat třídu, jež zprávu obdržela – i speciálního příjemce super – který zajistí, že se bude metoda hledat jen v nadtřídách. Podívejme se na obrázek 5.8; je to ještě jednodušší, než tomu bylo u instancí...

Třída „NSObject“

]

age

nadt ída

ess

m elf

[s

Třída „MyClass“

-(int)integerValue { ... } -(void)message { ... } [se

lf m

es

sa

ge

]

e]

u Val

ger

nte er i

nadt ída p

[su Třída „MyOtherClass“

e]

u Val

er teg

lf in

[se

[se

lf i

nte

ge

rVa

lue

]

Obrázek 5.8: Varianta pro třídy se od instanční nijak neliší

Je dobře si znovu připomenout, že v Objective C můžeme kdykoli poslat libovolnou zprávu kterémukoli objektu: ve skutečnosti tedy neexistují žádné „zprávy pro instance“ ani „zprávy pro třídy“; všechny zprávy jsou zcela rovnocenné a můžeme je posílat jak instancím, tak i třídám! Použití znaků „-“ a „+“ v deklaraci zpráv v rozhraní tedy hraje jen okrajovou roli: jeho jediným smyslem je napovědět čtenáři (a překladači), které zprávy máme v úmyslu posílat instancím a které třídám. Překladač tuto informaci zpracuje pouze tak, že pokud tento úmysl nedodržíme, varuje nás – ale program přeloží přesně stejně, jako kdyby zprávy nijak rozlišeny nebyly.

Objekty a Objective C

-(int)integerValue { ... }

5.7 Metody tříd

Ukázka elektronické knihy, UID: KOS180655


100

COCOA – ÚVOD DO PROGRAMOVÁNÍ NA PLATFORMĚ APPLE

Naproti tomu samozřejmě rozdělení metod v implementaci na metody tříd a metody instancí je naprosto reálné a zásadní: dostane-li zprávu instance, hledají se odpovídající metody jen a jenom mezi metodami uvedenými znakem „-“; dostane-li – přesně touž! – zprávu třída, hledají se odpovídající metody jen a jenom mezi těmi, jež jsou uvedeny znakem „+“. Zde platí určitá okrajová výjimka, týkající se kořenové třídy; více si k tomu řekneme v příští kapitole v souvislosti se službami třídy NSObject.

5.8 Pozdní vazba Uvědomme si dobře ten nejdůležitější rozdíl mezi zasíláním zpráv, využívaným v objektovém prostředí, a mezi voláním funkcí, používaném v jazycích typu C či C++: při zasílání zpráv to, jaká operace bude na základě přijetí zprávy provedena, rozhodne až přijímající objekt ve chvíli, kdy zprávu dostal. Protože se takto vazba mezi požadavkem toho, kdo zprávu odesílá, a reakcí toho, kdo ji přijímá, naváže co nejpozději to je možné – tedy až v okamžiku, kdy příjemce za běhu programu zprávu dostane –, nazývá se tento systém často také pozdní vazba. Výhodou pozdní vazby je nesmírná flexibilita: představme si třeba tu nejjednodušší funkci pro výpočet aritmetického průměru dvou čísel: CGFloat average(id o1,id o2) { return ([o1 doubleValue]+[o2 doubleValue])/2.; } Zápis „2.“ je v C ekvivalentní zápisu „2.0“ – v čísle stačí jen jediná číslice a tečka (nebo znak „e“ pro exponent), aby se jednalo o korektní desetinnou konstantu. Bezproblémový a správný je dokonce i třeba zápis „.1“ pro desetinu; podobný uvidíme v jednom z příkladů v příští kapitole.

Pokud bychom něco podobného napsali v klasickém jazyce C, byla by pro každý typ hodnot zapotřebí jiná funkce: ta, jež počítá průměr „intů“ by neuměla spočíst průměr „floatů“, o ostatních variantách ani nemluvě. C++ či Java jsou na tomo něco málo lépe. Tam by bylo možné jedinou funkcí počítat aritmetický průměr různých objektů, jež by však musely všechny být instancemi jedné jediné třídy – pro kterou by funkce average musela být přímo určena – nebo jejích dědiců (v Javě by asi nejlepší varianta umožnila práci s objekty, jež implementují totéž rozhraní – pokud by ovšem programátor naší funkce average na definici vhodného rozhraní předem pomyslel). Ne tak v Objective C; zde je díky systému zpráv tato funkce naprosto a neomezeně flexibilní: je úplně jedno, jaké objekty budou jejími parametry – jeden může representovat třeba celé číslo, kdežto druhý matici (jež po přijetí zprávy doubleValue spočte a vrátí determinant). Stejně dobře by funkce pracovala s objektem „textové pole v uživatelském rozhraní“, jež po přijetí zprávy doubleValue vrací svůj obsah interpretovaný jako číslo... Tato flexibilita není jen samoúčelnou hříčkou; přináší dvě velmi podstatné výhody:

5. Objekty a Objective C

Ukázka elektronické knihy, UID: KOS180655


Turn static files into dynamic content formats.

Create a flipbook
Cocoa (Ukázka, strana 99) by Kosmas-CZ - Issuu