home *** CD-ROM | disk | FTP | other *** search
/ Chip 2004 October / Chip_2004-10_cd1.bin / redakce / chip_txt / texty / txt / 148-152.txt < prev    next >
Text File  |  2004-09-02  |  20KB  |  107 lines

  1. Nßhrada d∞diΦnosti v objektovΘm programovßnφ
  2. Podt°φdy, delegßti, vklßdßnφ - jak se to r²muje?
  3. V tomto Φlßnku se seznßmφme s technikami objektovΘho designu, je₧ v opodstatn∞n²ch p°φpadech umo₧≥ujφ vyhnout se neÜikovnΘmu d∞d∞nφ a vytvß°enφ nov²ch t°φd: p∙jde o vyu₧φvßnφ delegßt∙ (a jim p°φbuznΘ techniky akce/cφl), o vyu₧itφ kategoriφ pro dopln∞nφ novΘho API ji₧ existujφcφ t°φd∞ a o vklßdßnφ objekt∙.
  4.  
  5. V °ad∞ objektov²ch prost°edφ je zvykem vyu₧φvat d∞diΦnost tak°ka na vÜe mo₧nΘ i nemo₧nΘ. Chceme omezit velikost okna nejv²Üe na 640 [215] 480 obrazov²ch bod∙? Dobrß, vytvo°φme si vlastnφ podt°φdu standardnφ systΘmovΘ t°φdy Window, v nφ₧ pat°iΦn²m zp∙sobem reimplementujeme metodu resize. Chceme tlaΦφtko, je₧ ukonΦφ aplikaci? Vytvo°φme vlastnφ podt°φdu standardnφ systΘmovΘ t°φdy Button, reimplementujeme v nφ metodu clicked tak, ₧e aplikaci ukonΦφ, a pro danΘ tlaΦφtko ji pou₧ijeme. Pot°ebujeme prioritnφ frontu objekt∙? Vytvo°φme podt°φdu standardnφ t°φdy Array a p°idßme pat°iΦnΘ slu₧by...
  6. Ve skuteΦnosti vÜak takovΘ nadu₧φvßnφ d∞diΦnosti nenφ ideßlnφm objektov²m designem a v praxi p°inßÜφ °adu problΘm∙: nez°φdka vede k tomu, ₧e bychom pot°ebovali vφcenßsobnou d∞diΦnost (je₧ je v C++ problematickß a jinde nenφ v∙bec), Φasto takΘ zp∙sobuje kombinaci slu₧eb z logicky r∙zn²ch blok∙ aplikace v jedinΘm zdrojovΘm souboru. V d∙sledku pak omezuje reusabilitu a komplikuje dalÜφ ·pravy k≤du.
  7.  
  8. PODT╪═DY
  9. ZaΦφt lze tφm, ₧e podt°φdy zcela b∞₧n∞ vytvß°φme. SouΦßstφ standardnφch knihoven Cocoa, kterou budeme pro ilustraci popisovan²ch technik pou₧φvat, je dokonce °ada t°φd, je₧ jsou p°φmo urΦeny k tomu, abychom v konkrΘtnφch aplikacφch pou₧φvali jejich konkrΘtnφ podt°φdy, a samy o sob∞ tΘm∞° nemajφ smysl (NSView). D∙le₧itΘ vÜak je, ₧e pro dosa₧enφ tΘho₧ cφle m∙₧eme vyu₧φt i jinΘ prost°edky, kterΘ jsou Φasto mnohem Üikovn∞jÜφ a znamenajφ menÜφ nßmahu pro programßtora (a menÜφ pravd∞podobnost chyb). Obecn∞ proto p°i objektovΘm designu platφ nßsledujφcφ pravidlo:
  10. Pokud nepracujeme s t°φdou, je₧ je p°φmo navr₧ena pro d∞d∞nφ, m∞li bychom nejprve zvß₧it, zda pro vy°eÜenφ danΘho problΘmu nalezneme vhodnou cestu bez vytvß°enφ nov²ch t°φd. Teprve pokud tomu tak nenφ, m∞li bychom zaΦφt uva₧ovat o podt°φdßch - ne d°φve. Podφvejme se znovu na p°φklady z ·vodu:
  11. * K omezenφ velikosti okna na 640 x 480 bod∙ je nejjednoduÜÜφ pou₧φt standardnφ okno a p°id∞lit mu tzv. delegßta - objekt, jeho₧ se okno "zeptß", mß-li zm∞nit velikost dan²m zp∙sobem.
  12. * Pro tlaΦφtko ukonΦujφcφ aplikaci je nejjednoduÜÜφ pou₧φt standardnφ tlaΦφtko, definovat jeho akci jako zprßvu terminate: a p°id∞lit mu jako cφl objekt aplikace.
  13. * Na prioritnφ frontu objekt∙ lze pou₧φt zcela obyΦejnou instanci t°φdy, reprezentujφcφ pole, a odpovφdajφcφ slu₧by doplnit prost°ednictvφm tzv. kategorie. (P°φpadn∞ m∙₧eme vytvo°it nov² objekt jako d∞dice zßkladnφ t°φdy a pole do n∞j vlo₧it. To je v²hodn∞jÜφ v p°φpad∞, ₧e po₧adujeme i dalÜφ atributy - dejme tomu, ₧e by naÜe prioritnφ fronta m∞la mφt jeÜt∞ jmΘno.)
  14.  
  15. DELEGACE
  16. NejjednoduÜÜφ nßhradou pro °adu p°φpad∙ neÜikovnΘho d∞d∞nφ je delegace. Princip je prost². Mφsto toho, aby se t°φda sama o vÜechno starala prost°ednictvφm sv²ch vlastnφch metod, obsahuje instance t°φdy odkaz na spolupracujφcφ objekt, tzv. delegßta, s nφm₧ nejr∙zn∞jÜφ akce prost°ednictvφm odpovφdajφcφch zprßv "konzultuje".
  17. Zßsadnφ v²hodou tohoto p°φstupu proti d∞d∞nφ je to, ₧e m∙₧eme funkΦn∞ odliÜnΘ bloky k≤du skuteΦn∞ rozd∞lit do r∙zn²ch t°φd. Objektov²m designem podle vzorce MVC (Model, View, Controller) se v rßmci tohoto Φlßnku podrobn∞ zab²vat nem∙₧eme; i bez v∞tÜφ teorie je vÜak z°ejmΘ, ₧e jde (nebo by aspo≥ m∞lo jφt) o pom∞rn∞ nezßvislΘ moduly. Zatφmco k≤d, kter² urΦuje, jak vypadß a jak funguje ovladaΦ pro zm∞nu velikosti, logicky pat°φ do objektu "okno", k≤d, kter² urΦuje, jak se okno m∙₧e zmenÜovat Φi zv∞tÜovat, pat°φ do ovladaΦe, kter² okno °φdφ, ale rozhodn∞ ne do okna samotnΘho (obr. 1).
  18. Vyu₧itφ delegace takΘ obvykle i zjednoduÜφ k≤d aplikace: jen v²jimeΦn∞ toti₧ delegßta p°ipravujeme jako nov², samostatn² objekt. ╚ast∞ji jde o objekt, kter² slou₧φ zßrove≥ pro vφce logicky souvisejφcφch v∞cφ - nap°φklad m∙₧e jako delegßt °φdit okno pro zobrazenφ seznamu polo₧ek a zßrove≥ jako zdroj dat p°edßvat tyto polo₧ky tabulce, je₧ je uvnit° okna zobrazuje. Krom∞ toho se jeÜt∞ m∙₧e starat o aktivaci/deaktivaci tlaΦφtek, je₧ nad polo₧kami pracujφ. 
  19. Zßkladnφ mechanismus delegace je prost² a m∙₧eme jej ve vlastnφch t°φdßch s v²hodou vyu₧φvat. Instance mß prost∞ k dispozici prom∞nnou obsahujφcφ odkaz na delegßta, metody pro p°φstup k tΘto prom∞nnΘ, je₧ se standardn∞ jmenujφ delegate a setDelegate - a p°ed d∙le₧it²mi operacemi a/nebo po jejich provedenφ se delegßta zeptß (Φi jej informuje).
  20. KonkrΘtnφ implementace zßvisφ na pou₧itΘm jazyce. V C++ je nutnΘ pro delegaci definovat abstraktnφ t°φdu, jejφmi₧ d∞dici budou vÜichni delegßti; to je samoz°ejm∞ neÜikovnΘ a nutφ nßs to vyu₧φvat vφcenßsobnΘ d∞diΦnosti, ale to je ji₧ dßno omezenφmi C++. V Jav∞ lze pro delegaci vyu₧φt interface, p°φpadn∞ (pro v∞tÜφ flexibilitu za cenu trochu slo₧it∞jÜφho k≤du) lze pou₧φt slu₧eb java.lang.reflect pro dosa₧enφ t²ch₧ mo₧nostφ, je₧ jsou v Objective C.
  21. Standardnφ technikou v Objective C je vyu₧itφ tzv. neformßlnφho protokolu pro deklaraci zprßv, je₧ jsou delegßtovi posφlßny. Nejde o nic jinΘho ne₧ o rozhranφ kategorie pro t°φdu NSObject. Dφky n∞mu p°ekladaΦ zprßvy znß a vyhneme se "warning∙m" p°i jejich posφlßnφ:
  22. // deklarace zprßv, posφlan²ch delegßtovi: @class OCJumper; @interface NSObject (OCJumperDelegate) -(BOOL)jumperShouldJump:(OCJumper*)jumper; // dotaz, zda mß b²t akce provedena @end // deklarace vlastnφ t°φdy: @interface OCJumper:... { id delegate;
  23. ... } -delegate; -(void)setDelegate:del; ... -(void)jump; ... @end
  24. Za zvlßÜtnφ zmφnku stojφ snad jen vyu₧itφ standardnφ metody respondsToSelector: (zd∞d∞nΘ od t°φdy NSObject) pro ov∞°enφ, zda delegßt zprßv∞ skuteΦn∞ rozumφ (na jejφm mφst∞ bychom v Jav∞ pou₧ili reflexi, v C++ nic podobnΘho nenφ). To je d∙le₧itΘ proto, abychom p°i implementaci delegßta mohli p°ipravit pouze metody, je₧ pot°ebujeme, a nemuseli se zdr₧ovat implementacφ ostatnφch:
  25. @implementation OCJumper -delegate { return delegate; } -(void)setDelegate:del { delegate=del; } ... -(void)performJump { // vlastnφ akce: nenφ v rozhranφ, jde o privßtnφ metodu ... } -(void)jump {
  26. // pokud delegßt rozumφ zprßv∞ jumperShouldJump: a odpovφ NO... if ([delegate respondsToSelector:@selector(jumperShouldJump:)] &&
  27. ![delegate jumperShouldJump:self]) return; // ... ned∞lßme nic [self performJump]; // jinak provedeme vlastnφ akci } ... @end
  28.  
  29. MECHANISMUS AKCE/C═L
  30. Mechanismus akce/cφl (action/target) je urΦitou alternativou delegace. Podobn∞ jako objekt m∙₧e udr₧ovat odkaz na delegßta, m∙₧e takΘ udr₧ovat odkaz na cφl (target), objekt, kter² bude informovßn o provedenφ n∞jakΘ zßsadnφ operace. JednoznaΦnΘ to b²vß u objekt∙ GUI - takto zßsadnφ operacφ pro tlaΦφtko je jeho stisknutφ, pro nabφdku v²b∞r n∞kterΘ z jejφch polo₧ek, pro textovΘ pole ukonΦenφ jeho editace apod.
  31. Mechanismus akce/cφl je proti delegaci flexibiln∞jÜφ v tom, ₧e i zprßva zasφlanß objektem je prom∞nnß, nenφ tedy pevn∞ urΦena, jako zprßva delegßta. Mφsto toho instance obsahuje vhodnou prom∞nnou - v Jav∞ String obsahujφcφ jmΘno metody (odeslanΘ pomocφ reflexe), v Objective C vyu₧ijeme typu SEL a standardnφ metody zd∞d∞nΘ od t°φdy NSObject pro odeslßnφ zprßvy - velmi p°ibli₧n∞ takto:
  32. // Akce/cφl pro tlaΦφtko [8212] princip @interface Button:... {
  33. SEL action; id target;
  34. ... } ... @end ... @implementation Button ... -(void)performClick { // tlaΦφtko bylo stisknuto [target performSelector:action withObject:target]; } ... @end
  35. V²hody proti vyu₧itφ d∞diΦnosti jsou obrovskΘ. Nejen₧e nemusφme "mφchat" k≤d pro °φzenφ aplikace s k≤dem samotnΘho tlaΦφtka, nemusφme ani psßt nic "navφc". Pokud je po₧adovanß slu₧ba ji₧ n∞kde k dispozici, prost∞ vezmeme tlaΦφtko a jen vhodn∞ nastavφme jeho target a action.
  36.  
  37. KATEGORIE
  38. Pokud chceme sestavit jen specifickΘ API, je₧ nepo₧aduje zßsadnφ rozÜφ°enφ slu₧eb, lze vzφt ji₧ hotovou t°φdu a slu₧by doplnit prost°ednictvφm tzv. kategorie. To se "klasickΘmu" vytvß°enφ podt°φdy hodn∞ podobß; z hlediska programßtora je vlastn∞ jedin² rozdφl v tom, ₧e nenφ t°eba vytvß°et novou t°φdu. NovΘ metody vÜak implementuje p°esn∞ stejn²m zp∙sobem, jako by tomu bylo p°i vyu₧itφ d∞diΦnosti. Podφvejme se na obr. 2 a 3; ty dob°e ilustrujφ jak podobnost, tak i rozdφly obou p°φstup∙. 
  39. Uka₧me si nejjednoduÜÜφ p°φklad implementace zßsobnφku. Jednou ze standardnφch t°φd, je₧ knihovny Cocoa nabφzejφ, je dynamickΘ pole objekt∙, NSMutableArray. Je celkem z°ejmΘ, ₧e nejjednoduÜÜφ bude implementovat zßsobnφk prßv∞ dopln∞nφm slu₧eb k tΘto t°φd∞ - v rozhranφ prost∞ jen deklarujeme novΘ zprßvy:
  40. @interface NSMutableArray (StackAccess) -(void)push:object; -pop; // pro prßzdn² zßsobnφk vyvolß v²jimku @end
  41. Implementace je vφcemΘn∞ z°ejmß - jen p°φmo p°evedeme zßsobnφkovß primitiva na primitiva dynamickΘho pole:
  42. @implementation NSMutableArray (StackAccess) -(void)push:object {
  43. [self addObject:object]; } -pop { id o=[[[self lastObject] retain] autorelease];
  44. [self removeLastObject]; return o; } @end
  45. Metody addObject:, lastObject a removeLastObject jsou standardnφmi metodami t°φdy NSMutableArray a jejich funkce je z°ejmß z jejich jmen. Metody retain, autorelease a jejich vyu₧itφ jsou danΘ zp∙sobem, jφm₧ Cocoa °φdφ sprßvu pam∞ti, a jejich vysv∞tlenφ by p°esßhlo rozsah Φlßnku.
  46. JakΘ jsou v²hody a nev²hody tohoto vyu₧itφ kategorie? 
  47. + Kategorie funguje stejn∞ dob°e s obyΦejnou t°φdou i se sdru₧en²mi t°φdami (class clusters) - s nimi by se obyΦejnß d∞diΦnost nedala p°φmo vyu₧φt. 
  48. + Objekty typu zßsobnφk jsou oboustrann∞ stoprocentn∞ kompatibilnφ s instancemi NSMutableArray (jde prakticky o objekty tΘ₧e t°φdy). N∞jak² modul tedy m∙₧e vytvo°it pole NSMutableArray a jin² m∙₧e s t²m₧ objektem pracovat jako se zßsobnφkem. To by nebylo mo₧nΘ u objekt∙ r∙zn²ch t°φd (platila by kompatibilita jen jednφm sm∞rem). 
  49. + P°φjemn²m d∙sledkem minulΘho bodu je neomezenΘ vyu₧itφ vÜech knihovnφch slu₧eb.
  50. Mßme-li nap°φklad slu₧by pro archivaci objekt∙ do formßtu XML, je₧ podporujφ pole, m∙₧eme je beze zm∞ny vyu₧φt i pro nßÜ zßsobnφk. Pokud bychom pro zßsobnφk m∞li samostatnou t°φdu, bylo by nutnΘ pou₧it² formßt XML rozÜφ°it tak, aby tuto t°φdu explicitn∞ podporoval. Podobn∞ je tomu i p°i sdφlenφ objekt∙ mezi r∙zn²mi procesy a podobn∞. 
  51. - Obecnou nev²hodou kategorie je, ₧e nenφ mo₧nΘ p°φmo p°idßvat instanΦnφ prom∞nnΘ. Pokud bychom to pot°ebovali, existujφ sice triky, jak to zaonaΦit, avÜak obvykle u₧ je lepÜφ vyu₧φt spφÜe vklßdßnφ objekt∙ (nebo "klasickou" d∞diΦnost, pokud nenarazφme na sdru₧enΘ t°φdy Φi na jin² problΘm). 
  52. - P°i vyu₧itφ kategorie tφmto zp∙sobem takΘ nelze zm∞nit standardnφ chovßnφ zßkladnφ t°φdy (to musφ z∙stat k dispozici pro moduly, je₧ t°φdu vyu₧φvajφ b∞₧n²m zp∙sobem). Pokud tedy po₧adovanΘ chovßnφ novΘho objektu nenφ pouh²m rozÜφ°enφm slu₧eb objektu p∙vodnφho, nelze kategorii pou₧φt. 
  53. Tam, kde je n∞kterß z t∞chto nev²hod kritickß, mßme k dispozici vklßdßnφ objekt∙.
  54.  
  55. VKL┴D┴N═ OBJEKT┘ A P╪ESM╠ROV┴N═ ZPR┴V
  56. Pro lepÜφ pochopenφ toho, jak vklßdßnφ objekt∙ funguje, je vhodnΘ se podφvat na obr. 2 a uv∞domit si, co se d∞je, kdy₧ objektu Zßsobnφk poÜleme n∞jakou zprßvu:
  57. * Pokud je odpovφdajφcφ metoda souΦßstφ t°φdy Zßsobnφk (je ve skupin∞ novΘ slu₧by), prost∞ se provede. 
  58. * Pokud tomu tak nenφ, hledß se odpovφdajφcφ metoda ve t°φd∞ Pole.
  59. Vklßdßnφ objekt∙ dosahuje tΘho₧ efektu trochu jinak: t°φda Zßsobnφk nenφ d∞dicem t°φdy Pole, ale obsahuje vlo₧en² objekt t°φdy Pole. T°φda je implementovßna tak, aby se zprßvy, jim₧ sama "nerozumφ", p°esm∞rovaly na tento vno°en² objekt (obr. 4). Implicitnφ d∞diΦnost tedy nahrazuje explicitnφ p°edßvßnφ zprßv. 
  60. Vklßdßnφ objekt∙ je slo₧it∞jÜφ ne₧ prostΘ vyu₧itφ d∞diΦnosti. Krom∞ nov²ch slu₧eb musφme navφc explicitn∞ implementovat p°edßvßnφ zprßv. V²m∞nou za to ovÜem zφskßme znaΦnou flexibilitu:
  61. * Vlo₧en² objekt nemusφ b²t vytvo°en hned p°i tvorb∞ hlavnφho objektu, lze jej vytvo°it, a₧ kdy₧ je poprvΘ zapot°ebφ. V n∞kter²ch p°φpadech to m∙₧e znamenat skuteΦn∞ zßsadnφ rozdφl - pokud se vytvß°φ mnoho instancφ zßkladnφch objekt∙, vlo₧enΘ objekty jsou velkΘ a pou₧φvajφ se z°φdka, m∙₧e tato technika mnohonßsobn∞ snφ₧it spot°ebu pam∞ti a zrychlit aplikaci.
  62. * Vlo₧en² objekt nemusφ b²t po celou dobu existence zßkladnφho objektu tent²₧. Podle pot°eby m∙₧e zßkladnφ objekt kdykoli nahradit objekt vlo₧en² jinou instancφ, dokonce i instancφ jinΘ t°φdy. Vlo₧en²ch objekt∙ m∙₧e b²t i vφce a zßkladnφ objekt se m∙₧e dynamicky rozhodnout, kterΘmu z nich zprßvu p°edß. Tak m∙₧eme efektivn∞ implementovat de facto vφcenßsobnou d∞diΦnost, ani₧ bychom narazili na nev²hody, je₧ jsou s nφ spjaty v jazycφch typu C++, je₧ ji nabφzejφ p°φmo.
  63. * Proto₧e p°edßvßnφ zprßv mezi zßkladnφm a vlo₧en²m objektem je "jejich internφ v∞c", skrytß v rßmci zapouzd°enφ uvnit° API zßkladnφho objektu a neovliv≥ujφcφ zbytek aplikace, m∙₧eme pro n∞j pou₧φt r∙znΘ nestandardnφ metody. Typick²m vyu₧itφm tΘto mo₧nosti jsou tzv. distribuovanΘ objekty - odkaz na objekt obsahuje identifikaci poΦφtaΦe a procesu a p°edßvßnφ zprßv je zajiÜt∞no prost°ednictvφm meziprocesovΘ komunikace a/nebo poΦφtaΦovΘ sφt∞. Tak m∙₧eme transparentn∞ "p°φmo" pracovat s objekty, je₧ jsou fakticky souΦßstφ jinΘho procesu na jinΘm poΦφtaΦi.
  64. DalÜφ v²hodou vklßdßnφ objekt∙ je i to, ₧e bez problΘm∙ funguje i se sdru₧en²mi t°φdami - "klasickß" d∞diΦnost je u t∞chto specißlnφch t°φd problematickß, resp. slou₧φ u nich pro zcela jin² ·Φel.
  65.  
  66. ROZHRAN═
  67. Pro ilustraci si ukß₧eme implementaci jednoduchΘho zßsobnφku pomocφ vklßdßnφ objekt∙, i kdy₧ zde by se kategorie hodila lΘpe. Rozhranφ je pom∞rn∞ jednoduchΘ - krom∞ deklarace API pot°ebujeme jen jednu instanΦnφ prom∞nnou, je₧ bude obsahovat odkaz na vlo₧en² objekt:
  68. @interface Stack:NSObject {
  69. NSMutableArray *array; } -(void)push:object; -pop; // pro prßzdn² zßsobnφk vyvolß v²jimku @end
  70. V praxi bychom asi vklßdßnφ objekt∙ vyu₧ili ve slo₧it∞jÜφch p°φpadech, kdy by instanΦnφch prom∞nn²ch bylo vφce.
  71.  
  72. IMPLEMENTACE
  73. Implementace je tentokrßt trochu slo₧it∞jÜφ, a proto si ji ukß₧eme v n∞kolika krocφch. Nejprve to nejjednoduÜÜφ: zßsobnφkovß primitiva p°evedeme na primitiva dynamickΘho pole prakticky stejn∞, jako tomu bylo u kategorie, jen mφsto odkazu self sßm na sebe pou₧ijeme odkaz na vlo₧en² objekt:
  74. @implementation Stack -(void)push:object {
  75. [array addObject:object]; } -pop { id o=[[[array lastObject] retain] autorelease];
  76. [array removeLastObject]; return o; }
  77. Celkem jednoduchß je i standardnφ implementace "konstruktoru" init, v n∞m₧ vytvo°φme vlo₧en² objekt:
  78. -init {
  79. [super init]; array=[[NSMutableArray alloc] init]; return self; }
  80. Pokud po₧adujeme jen novΘ API (reprezentovanΘ zprßvami push: a pop), jsme hotovi. Sice jsme museli napsat nepatrn∞ vφce k≤du ne₧ p°i pou₧itφ kategorie podt°φdy, zato se nßm vÜak neplete dohromady starΘ a novΘ API a pou₧itß technika funguje stejn∞ dob°e se sdru₧en²mi i s normßlnφmi t°φdami. Navφc mßme v²hodu mo₧nosti inicializovat vlo₧en² objekt dynamicky a₧ v p°φpad∞ pot°eby - prost∞ bychom zruÜili implementaci metody init a na zaΦßtek metod push: a pop bychom p°idali °ßdek if (!array) array=[[NSMutableArray alloc] init];
  81. V obecnΘm p°φpad∞ vÜak to, ₧e se nßm neplete starΘ a novΘ API, p°inßÜφ vlastnφ problΘmy, nebo¥ to znamenß, ₧e nad objekty t°φdy Stack nem∙₧eme u₧φvat slu₧eb t°φdy NSMutableArray. To proto, ₧e jsme dosud neimplementovali vlastnφ p°esm∞rovßnφ zprßv - a₧ dosud jsme vyu₧φvali jen vklßdßnφ objekt∙; hned to napravφme.
  82.  
  83. P╪ESM╠ROV┴N═ ZPR┴V
  84. Pro p°esm∞rovßnφ zprßv musφme mφt k dispozici odpovφdajφcφ slu₧bu runtime: jde o algoritmus p°edßvßnφ zprßvy objektu, kter² musφ obsahovat pln∞ dynamickß "zadnφ vrßtka" pro p°φpad, ₧e se nenajde odpovφdajφcφ metoda. V Objective C s knihovnami Cocoa je mo₧nost p°esm∞rovßnφ standardn∞. Lze ji zajistit i v Jav∞ s nestandardnφmi knihovnami (standardnφ Java ji ani s vyu₧itφm reflexe nenabφzφ). Pokud se v ₧ßdnΘ nadt°φd∞ nenajde odpovφdajφcφ metoda, runtime systΘm se pokusφ odeslat zprßvu dynamicky, nezßvisle na metodßch, je₧ jsou souΦßstφ t°φd. TakovΘ dynamickΘ odeslßnφ zprßvy pak probφhß ve dvou krocφch:
  85. * Nejprve se runtime systΘm objektu "zeptß", jakΘ jsou typy argument∙ a nßvratovß hodnota odpovφdajφcφ danΘ zprßv∞.
  86. * Pak runtime systΘm vytvo°φ "balφΦek" reprezentujφcφ zprßvu i jejφ argumenty (aby to bylo korektn∞ mo₧nΘ s libovoln²mi typy, musel nejprve prob∞hnout prvnφ krok) a ten objektu p°edß. Objekt s nφm m∙₧e ud∞lat cokoliv, v naÜem p°φpad∞ jej p°edß vlo₧enΘmu objektu, aby jej zpracoval za n∞j.
  87. Oba kroky jsou realizovßny pomocφ standardizovan²ch zprßv. Pro prvnφ z nich slou₧φ zprßva methodSignatureForSelector:, jejφm₧ argumentem je tzv. selektor (v podstat∞ zak≤dovanΘ jmΘno) danΘ zprßvy. Vrßcenß hodnota je specißlnφ objekt t°φdy NSMethodSignature, kter² podrobn∞ urΦuje vÜechny atributy metody, tj. poΦet a typy jejφch argument∙ i typ jejφ nßvratovΘ hodnoty. Pro druh² krok je urΦena zprßva forwardInvocation:, jejφm₧ argumentem je specißlnφ objekt t°φdy NSInvocation. Ten slou₧φ jako v²Üe zmφn∞n² "balφΦek" - jeho souΦßstφ jsou konkrΘtnφ hodnoty argument∙ i selektor zprßvy a jeho prost°ednictvφm se p°edßvß i nßvratovß hodnota.
  88. Znφ to mo₧nß slo₧it∞, ale konkrΘtnφ implementace p°esm∞rovßnφ vÜech neznßm²ch zprßv na vlo₧en² objekt je velmi jednoduchß:
  89. -(NSMethodSignature*)methodSignatureForSelector:(SEL)sel { return [array methodSignatureForSelector:sel]; } -(void)forwardInvocation:(NSInvocation*)inv {
  90. [inv invokeWithTarget:array]; } @end
  91. V prvnφ metod∞ si vy₧ßdßme signaturu od vlo₧enΘho objektu. V implementaci druhΘ metody forwardInvocation: jen p°edßme objektu inv po₧adavek, aby zprßva, ji₧ reprezentuje, byla zaslßna objektu array - to zajistφ standardnφ metoda invokeWithTarget:, je₧ je souΦßstφ knihovnφ implementace t°φdy NSInvocation.
  92.  
  93. V▌HODY A NEV▌HODY
  94. O n∞kter²ch v²hodßch vklßdßnφ objekt∙ a p°esm∞rovßnφ zprßv jsme u₧ hovo°ili, je jich vÜak vφce: 
  95. + Vklßdßnφ objekt∙ a p°esm∞rovßnφ zprßv korektn∞ podporuje sdru₧enΘ i normßlnφ t°φdy. 
  96. + Vlo₧en² objekt nemusφ b²t vytvo°en hned p°i tvorb∞ hlavnφho objektu, lze jej vytvo°it "on-demand" a₧ ve chvφli, kdy je poprvΘ zapot°ebφ. 
  97. + Vlo₧en² objekt nemusφ b²t po celou dobu existence zßkladnφho objektu t²₧. Podle pot°eby m∙₧e zßkladnφ objekt kdykoli nahradit vlo₧en² objekt jinou instancφ, v komplexn∞jÜφch p°φpadech i instancφ jinΘ t°φdy. Podobn∞ m∙₧e b²t vlo₧en²ch objekt∙ vφce a zßkladnφ objekt se m∙₧e podle podmφnek a pot°eby dynamicky rozhodnout, kterΘmu zprßvu p°edß. 
  98. + Proto₧e p°edßvßnφ zprßv mezi zßkladnφm a vlo₧en²m objektem je "jejich internφ v∞cφ", skrytou v rßmci zapouzd°enφ uvnit° API zßkladnφho objektu a neovliv≥ujφcφ zbytek aplikace, m∙₧eme pro n∞j pou₧φt r∙znΘ nestandardnφ metody. 
  99. + P°i vklßdßnφ objekt∙ a p°esm∞rovßnφ zprßv lze snadno skr²t API, je₧ nechceme publikovat (jako by z∙stalo skryto kompletnφ API t°φdy NSMutableArray, kdybychom p°esm∞rovßnφ zprßv neimplementovali). Stejn∞ dob°e m∙₧eme p°i p°esm∞rovßvßnφ dynamicky volit, kterΘ zprßvy p°edßme, a kterΘ ne. 
  100. - Proti vyu₧itφ kategorie ztrßcφme v²hodu oboustrannΘ kompatibility (dostaneme-li instanci t°φdy NSMutableArray, nem∙₧eme ji p°φmo vyu₧φvat jako zßsobnφk). 
  101. Proti d∞diΦnosti nemß p°esm∞rovßnφ tak°ka ₧ßdnou nev²hodu, nepoΦφtßme-li t∞ch cca osm °ßdk∙ zdrojovΘho k≤du, je₧ musφme napsat navφc pro implementaci vlastnφho p°esm∞rovßnφ.
  102.  
  103. SHRNUT═
  104. P°esto₧e d∞diΦnost je a z∙stane zßkladnφ a nesmφrn∞ cennou vlastnostφ objektov²ch systΘm∙, je t°eba dßt si pozor na jejφ nadu₧φvßnφ, je₧ n∞kdy vede ke zbyteΦn∞ komplikovanΘmu k≤du a jindy k nevhodnΘmu designu (jmenovit∞ k "pror∙stßnφ" modul∙, je₧ by m∞ly v rßmci modelu MVC z∙stat samostatn²mi). P°itom existuje °ada technik, kterΘ dokß₧φ d∞diΦnost efektivn∞ a s n∞kter²mi v²hodami nahradit - od jednoduchΘ delegace, p°φstupnΘ prakticky v libovolnΘm prost°edφ, a₧ po nejflexibiln∞jÜφ vklßdßnφ objekt∙ a p°esm∞rovßnφ, je₧ ovÜem vy₧aduje dynamick² objektov² jazyk s vhodn²m runtime. M∙₧eme tedy odpov∞d∞t na otßzku z nadpisu: Podt°φdy, delegßti, vklßdßnφ - jak se to r²muje? Inu, t°eba takto: Na podt°φdy bacha, delegßt, ten fachß, vklßdßnφ je °acha, tak se to r²muje.
  105. Ond°ej ╚ada 
  106.  
  107.