Vynechejme nyní trochu únavné teorie a podívejme se rovnou na následující příklad, ve kterém budeme uživateli pokládat celou spoustu otázek. Pro jednoduchost nás nebudou zajímat jeho odpovědi, pouze budeme kontrolovat, zda uživatel napsal "ano" nebo "ne".
odpoved_ok = false while (not odpoved_ok) puts 'Máš rád zvířata?' odpoved = gets.chomp.downcase if (odpoved == 'ano' or odpoved == 'ne') odpoved_ok = true else puts 'Zadejte "ano" nebo "ne"' end end odpoved_ok = false while (not odpoved_ok) puts 'Už jsi někdy jedl psa?' odpoved = gets.chomp.downcase if (odpoved == 'ano' or odpoved == 'ne') odpoved_ok = true else puts 'Zadejte "ano" nebo "ne"' end end odpoved_ok = false while (not odpoved_ok) puts 'A co vlka, vlka jsi měl?' odpoved = gets.chomp.downcase if (odpoved == 'ano' or odpoved == 'ne') odpoved_ok = true else puts 'Zadejte "ano" nebo "ne"' end end odpoved_ok = false while (not odpoved_ok) puts 'A medvěda jsi jedl?' odpoved = gets.chomp.downcase if (odpoved == 'ano' or odpoved == 'ne') odpoved_ok = true else puts 'Zadejte "ano" nebo "ne"' end end
Je vidět, že tento postup není příliš praktický. Ne, že bychom tímto způsobem program nevytvořili, ani nemůžeme říct, že by nefungoval tak, jak má. Je ale hned na první pohled vidět, kolik práce nás jeho vytvoření stálo a přitom se se určité části programu pouze pravidelně opakují…
K tomu nám ruby umožňuje vytvářet a především používat vlastní metody. Zkusme vytvořit následující jednoduchou metodu, kterou označme pozdrav
.
def pozdrav puts 'Ahoj!' end pozdrav pozdrav puts 'Jak se vede?' pozdrav
zobrazí
Ahoj! Ahoj! Jak se vede? Ahoj!
V příkladu jsme definovali vlastní metodu pozdrav
a tu pak několikrát použili. No není to pěkné?
Pokud bychom chtěli metodu pozdrav
změnit, stačí jenom upravit její definici nahoře a všude tam, kde metodu používáme, se použije její nová aktualizovaná verze. Tzn. již žádné hledání v programu a úpravy typu Najít & Nahradit.
Parametry metod
Vraťme se nyní k úvodnímu příkladu. Abychom si mohli tento program zjednodušit, potřebovali bychom metodě předávat nějaký parametr obsahující naši otázku. I na toto ruby pamatuje:
def otazka text odpoved_ok = false while (not odpoved_ok) puts text odpoved = gets.chomp.downcase if (odpoved == 'ano' or odpoved == 'ne') odpoved_ok = true else puts 'Zadejte "ano" nebo "ne"' end end end otazka 'Máš rád zvířata?' otazka 'Už jsi někdy jedl psa?' otazka 'A co vlka, vlka jsi měl?' otazka 'A medvěda jsi jedl?'
Tím se nám program zjednodušil nejen svým rozsahem, ale také svým obsahem. Zdrojový kód programu by určitě neměl působit dojmem nějaké šifry!
Lokální proměnné
Lokální proměnné jsou takové proměnné, které se objevují uvnitř metody a jsou vidět (dostupné) pouze v této metodě a nikde jinde. Zkusme následující příklad.
def umocneni cislo vysledek = cislo * cislo puts 'mocnina čísla ' + cislo.to_s + ' je ' + vysledek.to_s end umocneni 5 puts vysledek
zobrazí
mocnina čísla 5 je 25 umocneni.rb:7: undefined local variable or method `vysledek' for main:Object (NameError)
Je vidět, že proměnná vysledek
existuje pouze v metodě umocnění
, a tak s ní není možno mimo tuto metodu dál pracovat. Na druhou stranu, to samé platí i pro proměnné definované mimo jakoukoliv metodu (tuto část programu můžeme nazývat např. hlavním programem). Zkusme tuto ukázku:
def likvidator promenna promenna = nil puts 'CHA, a máš po proměnné!' end promenna = 'Nějaký velmi dlouhý a důležitý text' likvidator promenna puts promenna
zobrazí
CHA, a máš po proměnné! Nějaký velmi dlouhý a důležitý text
tedy, obsah proměnné promenna zůstal zachován.
Tato vlastnost platnosti proměnných v programu je velmi důležitá, a proto si ji dobře promyslete!
Návratové hodnoty metod
Přestože jsou globální i lokální proměnné navzájem neviditelné, často potřebujeme výsledek nějaké funkce dosadit do nějaké proměnné. K tomuto (a nejen k tomu) slouží návratové hodnoty metod. Zkusme následující:
def metoda puts 'Včera jsem byl doma.' puts 'Dělal jsem úkoly do školy.' 'A koukal na televizi' end metoda puts pokus = metoda puts pokus puts pokus2 = puts pokus puts pokus2
zobrazí
Včera jsem byl doma. Dělal jsem úkoly do školy. Včera jsem byl doma. Dělal jsem úkoly do školy. A koukal na televizi A koukal na televizi nil
Takže co se to vlastně stalo?
- První volání metody
metoda
zobrazilo výstup přesně tak, jak bychom očekávali. - Druhým voláním metody
metoda
jsme přiřadili do proměnnépokus
její návratovou hodnotu. Tou je vždy poslední proměnná či hodnota uvedená na závěr metody. - Poslední volání
puts pokus
ukazuje na jednu zajímavou vlastnost samotné metodyputs
, která spočívá v tom, že metoda posílá jako poslední hodnotu nil, která nás informuje o konci textu.
Na závěr zkusme trochu složitější program, kterému zadáme nějaké číslo v rozmezí od 0 po 99 a program nám napíše, jak bychom toto číslo vyslovili.
def rekni_cislo cislo cislice = ['nula', 'jedna', 'dva', 'tri', 'ctyri', 'pet', 'sest', 'sedm', 'osm', 'devet'] desitky = ['deset', 'dvacet', 'tricet', 'ctyricet', 'padesat', 'sedesat', 'sedmdesat', 'osmdesat', 'devadesat'] vyslov = '' desitek = cislo/10 if (desitek != 0) vyslov = desitky[desitek-1] if (cislo != 10*desitek) vyslov = vyslov + cislice[cislo-10*desitek] end else vyslov = vyslov + cislice [cislo] end vyslov end puts rekni_cislo(5) puts rekni_cislo(8) puts rekni_cislo(50) puts rekni_cislo(87) puts rekni_cislo(66) puts rekni_cislo(10
program zobrazí
pet osm padesat osmdesatsedm sedesatsest deset
Metodu funkce
s parametrem v podobě čísla 5
můžete zavolat funkce 5
i funkce(5)
. Obojí syntaxe je možná.
Příklady 8
- V předchozím příkladu je chyba a program nebude správně zapisovat čísla 11, 12, 13, … 19. Opravte program tak, aby fungoval správně, nebo napište svou vlastní verzi, ve které bude chyba odstraněna.
- Upravte první příklad tohoto cvičení tak, aby nejenom používal metody, ale také si zapamatoval výsledné hodnoty. Pro uchování hodnot můžete použít proměnné nebo lépe pole. Výsledek pak najednou vypište, odpovědi od sebe oddělte symbolem středník.
- Napište program, který vám spočítá faktoriál nějakého čísla. Faktoriál čísla n, tedy n!. Faktoriál se spočítá takto: n! = n(n-1)(n-2)(n-3)…1, tedy např. 5! = 5.4.3.2.1 = 120. Pro výpočet faktoriálu je potřeba volat funkci pro výpočet faktoriálu rekurzivně. ;-)
Příště se podíváme na třídy. Nebudeme se sice vracet do školních lavic, ale podíváme se zblízka na to, jak jsou konstruovány objekty a jak se s nimi v Ruby pracuje.