Zprávy jsou jediným prostředkem, který mohou objekty při vzájemné komunikaci používat. Mohou být předávány s parametry či bez nich a vždy vrací nějakou hodnotu. Zprávy rozlišujeme na unární, binární a slovní.
Unární zprávy
Unární zprávy nepřijímají žádné parametry. Mohou vypadat například nějak takto:
asSmallAngleDegrees
"Return the receiver normalized to lie within the range (-180, 180)"
| pos |
pos := self \\ 360.
pos > 180 ifTrue: [ pos := pos - 360 ].
^ pos
Jedná se o metodu třídy Number. První řádek metody tvoří její selektor (asSmallAngleDegrees). Selektory zpráv začínají z konvence malým písmenem. Tvoříme je tak, aby byly při použití co nejčitelnější. Pokud selektor zprávy tvoří více slov, první písmeno každého z nich kapitalizujeme.
Je velmi vhodné na začátku každé metody uvést komentář (ohraničený uvozovkami), který funkci metody popíše, a popřípadě v něm i uvést příklad použití, pokud není zcela zřejmé.
Pomineme-li komentáře, musí začínat každá metoda seznamem lokálních proměnných, má-li nějaké. Každá proměnná má po své inicializaci hodnotu nil (jedinečná instance třídy UndefinedObject). Před použitím je třeba ji inicializovat. Pokud tak neučiníme, kompilátor nás sice bude varovat, ale zkompilování metody nám nezakáže. Rovněž budeme upozorněni v případě, že nějaká lokální proměnná je v seznamu uvedena nadbytečně či naopak v seznamu chybí.
Následuje kód metody, který tvoří sekvence výrazů (jednotlivé výrazy se oddělují tečkou). Pseudo-proměnná self referencuje objekt, který je příjemcem zprávy, v našem případě tedy nějaké číslo (obdoba this). Dvě zpětná lomítka \\ jsou binární zpráva používaná pro operaci modulo (pro celočíselné dělení slouží zpráva //).
Na konci každé metody je uveden návratový výraz (začínající znakem stříšky). Může se samozřejmě vyskytovat i někde uvnitř metody, pokud potřebujeme ukončit nějakou její alternativní větev. Za návratovým výrazem musí být metoda ukončena. Totéž platí i pro blok, pokud se v něm návratový výraz vyskytuje. V případě, že návratový výraz neuvedeme, vrací se implicitně hodnota self, tedy totéž, jako bychom napsali^self.
Binární zprávy
cout << 'Hello world' << endl.
I takto může vypadat Smalltalk. Binární zprávu tvoří binární selektor, za nímž je uveden parametr. Například metoda pro modulo třídyNumer vypadá takto:
\\ aNumber ^self - (self // aNumber * aNumber)
Při výběru selektorů binárních zpráv poskytuje Squeak brutální volnost. Jejich délka není omezena, přičemž povoleny jsou následující znaky:
-!%&*+,/|<=>?@\`~†°˘Ł§ŽŠ™‰‹›Ľ˝‡ˇ
plus ještě několik dalších paznaků. Výjimku z nich tvoří mínus, které se smí vyskytovat pouze na začátku binárního selektoru, a roura, kterou lze jako binární selektor použít pouze samostatně. Nejčastějšími operátory jsou například =, ~= (nerovnost), == (identita), ~~ (neidentita), <, >, <=,>=, čárka (konkatenace kolekcí a řetězců), /, +, -, *, @ (vytvoření bodu), | (or), & (and).
('a', 'bc') = 'abc' "true" ('a', 'bc') == 'abc' "false" (Point x: 10 y: 20) = (10@20)
Pro booleovské operace and a or se krom výše zmíněných operátorů setkáte ještě s metodami and: a or:, které přijímají jako parametr blok. Jedná se o slovní zprávy používající zkrácené vyhodnocení. Operátory | a & naopak své parametry vůbec nevyhodnocují, protože jako parametr nečekávají blok, ale booleovský objekt. Např.:
(a = 1) and: [ b = 2 ] ifTrue: [ "dělej něco" ].
false and: [ Transcript show: 'Nevypise se'. true ] "výsledkem je false"
true and: [ Transcript show: 'Vypise se'. false ] "výsledkem je false"
(a = 1) & (b = 2) ifTrue: [ "dělej něco" ].
true & [ Transcript show: 'Nevypise se'. true ] "nevhodné, výsledkem je blok"
true & [ Transcript show: 'Vypise se'. true ] value "nevhodné, výsledkem je true"
Při tvorbě vlastních operátorů je samozřejmě jistá střídmost na místě. Na dlouhou stranu, pokud si vytvoříte například vlastní operátor =================================== pro vaši relaci jménem superrovnost, dáte tím jistě jeho význam najevo více než dostatečně :-)
Slovní zprávy
Slovní zprávy přijímají jeden či více argumentů. Jako příklad si vytvoříme ve Squeaku neexistující zprávu třídy Number jménemdownTo:do:
downTo: stop do: aBlock
"10 downTo: 1 do: [ :i | Transcript show: i; cr ]"
| nextValue |
nextValue := self.
[ nextValue >= stop ] whileTrue: [
aBlock value: nextValue.
nextValue := nextValue - 1
]
Všimněte si, že jsme nepoužili návratový výraz. Jména parametrů (stop, aBlock) nehrají při vzájemném rozlišování metod žádnou roli. Protože se u nich neudává ani žádná informace o typu, je pro identifikaci metody rozhodující pouze její selektor (v našem případě#downTo:do:).
Jména selektorů a parametrů je velmi vhodné dobře zvážit, aby výsledek byl co nejčitelnější a nejzřejmější. Proto jsou selektory pojmenovávány tak, aby při použití co nejvíce připomínaly přirozenou anglickou větu.
Jména parametrů pak uvádíme tak, aby bylo na první pohled zřejmé, co je očekáváno. Je vhodné je volit podle jména předpokládaného typu doplněného anglickým neurčitým členem (anInteger, aNumber, aBlock, aString apod.).
Slovní zprávy mají vždy pevně vyhrazený počet parametrů. Pokud je třeba předávat neohraničenou množinu hodnot, použijeme jako jeden z parametrů kolekci (např. pole). O kolekcích bude řeč později.
Připomínám, že to, co je skutečně předáno jako parametr, nelze v době překladu nijak omezit. Poněkud nestandardní nicméně platné použití předchozí metody by mohlo vypadat například takto:
10 downTo: 1 do: Character
Místo bloku jsme metodě poskytli jako druhý parametr třídu Character, která shodou okolností implementuje také metodu jménemvalue:. Tato metoda pouze vrací znak dané ASCII hodnoty a nemá žádný vedlejší efekt. Výsledný cyklus proto nic neudělá.
Browser
Browser je základní vývojový nástroj programátorů ve Smalltalku. Nyní se s ním velmi zběžně seznámíme, aby doposud nabyté informace dostaly konkrétnější obrysy. Okno browseru vypadá přibližně takto.
Možností, jak otevřít browser, je několik. Mimo jiné např.:
- klik levým tlačítkem na plochu – open – browser
- klik levým tlačítkem na plochu – stisknout Alt+b
- vysunout záložku Tools, táhnutím myší přetáhnout ikonku broweru na plochu
- v jakémkoliv textovém okně Squeaku označit text reprezentující jméno třídy – vyvolat kontextové menu – more – browse it
- v jakémkoliv textovém okně označit text reprezentující jméno třídy – stisknout Alt+b
- vyhodnotit výraz Browser fullOnClass: MojeTrida
Pokud o funkci browseru chcete získat alespoň mlhavou představu i bez nainstalovaného Squeaku, můžete se podívat např. sem. Pokud by umožňoval upravovat zdrojové kódy (což není technický problém a existuje verze, která to umí), bylo by to víceméně ekvivalentní tomu, jako byste měli nainstalován Linux s Apachem, na němž by běžela webová aplikace umožňující z prohlížeče za běhu systému procházet a měnit své vlastní zdrojové kódy včetně zdrojových kódů Apache a dokonce i linuxového jádra.
Okno browseru má pět základních oken. V prvním je seznam kategorií tříd. Při vyvolání kontextového menu nad tímto seznamem pomocí pravého či prostředního tlačítka (dle nastavení) získáte možnost kategorie mazat, přejmenovávat, vytvářet (add item), prohledávat atd. Při výběru některé kategorie se ve spodním největším okně zobrazí šablona pro vytvoření nové třídy.
Druhé okno obsahuje seznam tříd dané systémové kategorie. Po vybrání některé třídy se ve spodním okně zobrazí její definice tak, jak jsme si ji ukázali v minulém dílu.
Další okno obsahuje seznam kategorií metod pro danou třídu. Po kliknutí na některou z kategorií se ve spodním okně objeví šablona pro zápis metody.
Čtvrté okno pak obsahuje seznam metod v dané kategorii. Výběrem některé metody se ve spodním okně zobrazí její zdrojový kód. Metody, jejichž jména začínají na velká písmena, jsou vkládány na začátek seznamu.
Poslední největší okno ve spodní části browseru obsahuje editor. Pokud v něm upravíme či vytvoříme nějakou metodu, změny uložíme vyvoláním kontextového menu a vybráním volby accept (Ctrl popř. Alt+s). Totéž platí i pro změnu definice třídy.
Z celé řady velmi užitečných tlačítek, která rozhraní browseru nabízí a s nimiž se později také seznámíme, jsou nejdůležitější tři:
- instace
- Vyvolání kontextu třídy. Spodní okno obsahuje definici třídy, další okna obsahují kategorie zpráv a metody implementované třídou, tedy zprávy, které budou vykonávat instance.
- class
-
Vyvolání kontextu metatřídy. Další okna zobrazují kategorie metod a metody vykonávané třídou. Třída a metatřída tvoří nerozlučnou dvojici. Každá třída má svoji metatřídu, která je vytvořena v okamžiku vzniku třídy. Ve spodním okně se ukáže definice metatřídy. Ta se od definice třídy značně liší. Vypadá nějak takto:
MyClass class instanceVariableNames: 'instVar1 instVar2'
Jak vidíte, jde sice o volání metody, ovšem v tomto případě se již nejedná o vytvoření metatřídy (ta byla vytvořena spolu s třídou), ale pouze o možnost změny seznamu instančních proměnných. Třídní proměnné pro metatřídy nemají příliš smysl. Možná vás napadne otázka, jaký je rozdíl mezi třídními proměnnými a instančními proměnnými metatřídy. Liší se v tom, že instance nemají k instančním proměnným metatříd přístup a metatřídy nemají přístup k instančním proměnným instancí.
Pro pořádek ještě uveďme, že pokud se v běžné metodě vyskytne self/super, referencuje instanční objekt. V případě, že self/super uvedeme v rámci rozhraní metatřídy, referencuje třídu, tj. instanci metatřídy.
- ?
-
vyvolání dokumentace k dané třídě ve spodním okně. Krom základního popisu funkce a účelu třídy by se sem měly psát informace o instančních a třídních proměnných, příklady použití atd. Tento komentář lze přirozeně rovněž vyvolat programově pomocí metody comment a libovolně zpracovat.
MyClass comment
Pokud z nějakého důvodu chcete, aby nápovědu generovala samotná třída, stačí tuto metodu přetížit. Můžete tak například krom vypsání samotné dokumentace dát povel k otevření okna s tutoriálem a podobně.