Jazyk Ruby: Rozdiel medzi revíziami

Z Kiwiki
Skočit na navigaci Skočit na vyhledávání
d (Zamyká „Jazyk Ruby“ ([edit=sysop] (na neurčito) [move=sysop] (na neurčito)))
 
(Žiaden rozdiel)

Aktuálna revízia z 21:53, 20. január 2010


Ruby

Ruby ako interpretovaný objektovo orientovaný jazyk

Ruby je programovací jazyk, ktorý vytvoril Yukihiro Matsumoto, s cieľom poskytnúť tvorivý spôsob programovania. Matsumuto chcel vytvoriť jazyk, s ktorým bude radosť pracovať a ktorý bude čo najprirodzenejší. Typickým príkladom je výpis pozdravu hello world:

puts Hello world!

Príkaz znamená vypíš reťazec Hello world – v angličtine put string Hello world... Prvou a základnou vecou, ktorú treba pri jazyku Ruby pochopiť, aby sme s ním mohli plnohodnotne pracovať je to, že ide o interpretovaný a absolútne objektvo orientovaný jazyk. Interpretované (skriptovacie) jazyky sú jazyky, ktoré su prekladané pomocu interpreteru až počas behu programu. Sú pomalšie ako kompilované jazyky, ale nemajú tak veľké formálne požiadavky (nie je potreba inicializovať premennú, jej dátový typ sa môže počas behu meniť, ukazovatele sú zbytočné). Mnoho iných interpretovaných jazykov, ako napríklad PHP alebo Java podporujú objektovo-orientované programovanie, avšak nie sú absolútne objektovo orientované. Je to preto, že tieto jazyky obsahujú tzv. primitívne typy, napríklad integer, float, string, boolean, ktoré slúžia na ukladanie dát, ale nie sú objektami.

Ruby je od týchto jazykov radikálne odlišné, pretože neobsahuje žiadne z týchto primitívnych typov. Ide o čisto objektovo orientovaný jazyk, takže všetko je objekt v absolútnom slova zmysle. Základnou myšlienkou objektovo orientovaného programovania (OOP) je, že program by mal byť zložený zo samostatných entít, objektov, pričom každý z nich je schopný komunikovať s ostatnými objektami. Každý objekt je teda zložený z metód (volateľného kódu, ktorý vykonáva určitú činnosť) a interne uložených dát. Táto metóda „zabalenia“ užitočných vecí do objektu sa nazýva zapuzdrefinie. Objekty v aplikácii OOP sú často prirovnateľné k objektom reálneho sveta, čo umožňuje ľašie pochopenie funkcie a postavenia objektov v programe. A rovnako ako v reálnom svete, objekty môžu byť začlenené podľa rôznych kritérií do tried. To znamená, že triedy sú typom objektu. Tak napríklad, číslo 1 je objektom triedy Fixnum a medzi jej metódy patrí napríklad metóda + , teda súčet. Tak isto nami vytvorený objekt Trabant môže patriť do triedy auto a obsahovať metódu zapni_motor.

Pochopenie vzťahov medzi triedami, objektami a metódami umožňuje zistiť, ako OOP funguje. Objekt z jednej triedy môže napríklad vyvolať akciu iného objektu inej triedy, bez ovplyvnenia stavu ďalších objektov v tej istej triede. Tiež môžeme zmeniť určitú vlastnosť objektu bez toho, aby to malo vplyv na iné objekty tej istej triedy – keďže objekt sa správa ako samostatná entita. Každý nový objekt je vytváraný z určitej triedy, z ktorej vychádza – tento proces je nazývaný aj konktretizácia. Vytvorené objekty medzi sebou môžu komunikovať a vyvolávať metódy, spôsobom otázok a odpovedí. V prípade OOP sú otázkami inštrukcie a odpoveďami návratová hodnota, resp. stavová správa indikujúca, či bola požadovaná inštrukcia úspešne vykonaná. Tak v našom príklade môže objekt šofér požadovať inštrukciu zapni_motor od objektu Trabant, pričom návratovou hodnotou môže byť informácia o úspešnom alebo neúspešnom naštartovaní motora.

Keďže Ruby je absolútne objektovo orientovaný, čokoľvek v ňom je buď objektom, triedou alebo metódou určitého objektu a tak budeme aj pristupovať k informáciám v nasledujúcich podkapitolách, či pôjde o čísla, textové reťace alebo polia. Spomenuté výrazy si postupne rozoberieme v nasledujúcom texte.

Inštalácia a vývojové prostredie Ruby

Ruby na OS Windows nainštalujeme stiahnutím kompletného inštalátora Ruby z adresy http://rubyinstaller.rubyforge.org a jeho následným nainštalovaním. Na všetkých novších verziách Mac OS X a Linux je Ruby nainštalovaný automaticky. Pre prácu s Ruby je dostačujúci akýkoľvek textový editor, napríklad WordPad alebo Poznámkový blok, pričom výsledný Ruby program je potrebné uložiť s príponou .rb . Tento je potom spustiteľný z príkazového riadku.

Ďalšou možnosťou práce s Ruby je rozhranie IRB (Interactive Ruby Shell), pre ktorého spustenie stačí napísať irb do príkazového riadku. IRB rozhranie umožňuje interaktívne poskytnúť výsledok nášho príkazu, takže je ideálny pre testovanie jednoduchých jednoriadkových príkazov – preto ho budeme občas používať aj v nasledujúcich príkladoch.

Čísla, reťazce, premenné a konštanty

Ruby podporuje ako celé čísla (integer), tak i čísla s desatinnou čiarkou(float), pričom veľkosť celých čísel v ňom nie je nijako obmedzená – jediným obmedzením je teda voľná pamäť počítača. Čísla v rozmedzí od -230 do 230-1 alebo -262 do 262-1 sú zaradené do triedy Fixnum, ostatné presahujúce daný rozsah sú triedy Bignum. Presvedčiť sa o tom môžeme jednoduchým príkazom:

irb> 1
=> 1

V tomto príklade sa môže zdať, že sme dostali identický výstup od vstupu. A predsa tomu nie je tak. Výstupom je novovytvorený plnohodnotný Ruby objekt. Volaním metódy class môžeme ľahko zistiť, do ktorej triedy patrí naše číslo 1:

irb> 1.class
=> Fixnum

Výsledok je jasný, každý objekt je priradený do svojej triedy. Ruby sa o to najnutnejšie postará sám, okrem toho umožňuje veľké čísla zapísať oddelené podtržítkami pre sprehľadnenie, napríklad:

irb>100_111_222_333_444
=>100111222333444

Desatinné čísla sa dajú písať s vložením desatinnej čiarky, napríklad 3,1415, alebo s exponentom 31415.0e-4. Môžeme písať aj čísla binárne, zapísaním 0b na začiatok, osmičkové s 0 na začiatku a hexadecimálne s pomocou predpony 0x. Zadané vstupy teda odpovedajú nasledovným výstupom:

irb>0b10101
=>21
irb>0134
=>668
irb>0xa321c
=>668188

Reťazce

Reťazce sa môžu uzavrieť do apostrofov (``) alebo úvodzoviek (””),takže výrazy ”Ahoj” a `Ahoj` sú identické. Ak chceme použiť apostrofy alebo úvodzovky v texte, môžeme ich kombinovať, alebo môžeme v texte miesto nich vložiť %q (apostrofy) alebo %Q (úvodzovky) spolu s jediným znakom a na mieste ukončenia daný znak. Rovnaký efekt bude mať použitie dvojice znakov { a }, popr. < a >, dokonca môžeme vypustiť znak Q. Takže nasledujúce výrazy sú ekvivalentné:

irb>Povedal: `Ahoj!`
irb>Povedal: %q/Ahoj!/
irb>Povedal: %q{Ahoj!}
irb>Povedal: %q<Ahoj!>    # výpis bude vždy: Povedal: `Ahoj!`

Reťazce sa spájajú znakom +, napríklad:

irb>jedna,  + dva,  + tri
=>jedna, dva, tri

Volaním metódy length zistíme dĺžku daného reťazca – objektu:

irb>jedna, dva, tri.length
=>15

Výsledok určitého matematického výpočtu v reťazci zobrazíme jeho ohraničením do znakov #{ a }, napríklad:

 irb>5+7 je po scitani #{5+7}”
=>5+7 je po scitani 12

Premenné

Ruby dokáže ukladať dáta v premenných, čo sú pomenovaní zástupcovia predstavujúci nejaké čísla, reťazce a ďalšie údaje. Na tieto dáta uložené v premennej na odkazuje použitím názvu danej premennej. Premenné začínajú malým znakom a-z alebo podčiarkovníkom _ , potom nasleduje ľubovoľný počet znakov názvu – môže to byť malé i veľké písmeno, číslo, podčiarkovník. Jedinou podmienkou je nepoužívať slová, ktoré pre seba rezervuje jazyk Ruby, napríklad výrazy vyjadrujúce podmienky (if, then, when, else, elseif..), pravdivostnú hodnotu (true, false) alebo ohraničenie skupiny príkazov (begin, end).

Krátky príklad definovania a práce s premennou teplota:

irb>teplota=20
=>20
irb>Teplota je +String(teplota)
=>Teplota je 20
irb>teplota=teplota+5
=>25
irb>Aktualna teplota je #{teplota}”
=>Aktualna teplota je 25

Z príkladu vidno, že ak chceme k reťazcu priradiť číslo, je potrebné použiť metódu String, alebo ohraničiť prennú znakmi #{ a }. Ekvivalentom metódy String je metóda to_s:

irb>Teplota je +teplota.to_s
=>Teplota je 25

Globálne premenné

Globálne premenné sú premenné platné v celom programe a začínajú znakom $:

$x, $datum, $abc_DEF

Premenné inštancií

Premenné začínajúce znakom @ sú premenné inštancií (inštancie) :

@x, @datum, @abc_DEF

Premenné inštancií na rozdiel od lokálnych premenných zachovávajú hodnoty do nich uložené, pokiaľ existuje ich príslušný objekt.

Konštanty

V Ruby je tiež možné vytvárať konštanty. Konštanta obsahuje určitú hodnotu, ktorá ostáva časovo nemenná. Každá konštanta začína veľkým písmenom, ktorým Ruby rozpozná, že sa jedná o konštantu. Konštanty umožňuje Ruby zmeniť, v takom prípade sa zobrazí upozornenie o tom, že daná konštanta bola už inicializovaná.

irb>TRPASLIKOV= 7
=>7

Symboly, polia a hash

Symboly

(v iných jazykoch nazývané atómy) sú podobné reťazcom. Môžu obsahovať znaky, čísla, podčiarkovník, ale začínajú dvojbodkou:

:a, :b2, :agent_007

Symboly sa používajú na ukladanie raťazcov, keď nie je požadovaný výstup na obrazovku; v kóde nedochádza k ich náhrade.

Polia

Polia predstavujú skupiny premenných rôznych typov ku ktorým je možné pristupovať prostredníctvom indexu:

pole=[a,b,14,zelena]
puts pole[2]                 # vypíše 14
pole[3,1]=modra            #nahradí 1 element od pozície 3 reťazcom modrá
puts pole                    #výpis bude: [”a”, ”b”, 14, ”modra”]

Hash (asociačné polia)

Hash je pole, ku ktorého premenným možno pristupovať namiesto indexov prostredníctvom textových reťacov. K jeho vytvoreniu sa používajú zložené zátvorky:

kolko_dni_ma_mesiac = { januar => 31, februar => 28, marec =>31}
kolko_dni_ma_mesiac[februar]        # vypíše 28

Podmienené výrazy, cykly, metódy a bloky

V nasledujúcich príkladoch je zobrazený obecný syntax príkazov vrátane voliteľných klauzulí (tieto nepovinné klauzule sú ohraničené hranatými zátvorkami): if :

if  logický_výraz  [then | :]
      kód1
[elseif
     kód2]
[else
    kód3]
end

unless:

unless logický_výraz [then | :]
     kód1
[else
    kód2 ]
end

case:

case hodnota
   when výraz [, porovnanie]… [then | :]
       kód1
when výraz [, porovnanie]… [then | :]
       kód2
...
[else
     kód]
end

Ternárny operátor:

výsledok = podmienka ? pravdivá_hodnota : nepravdivá_hodnota

while:

while podmienka [do | :]
     kód
end

until:

until podmienka [do | :]
    kód
end

for:

for premenná [, premenná...] in kolekcia [do | :]
    kód
end

Iterátory jazyka Ruby

Okrem definovaných cyklov podporuje Ruby iterátory, metódy vstavané do položiek, s ktorými sa pracuje. Umožňujú vytvárať cykly a nahrádzať častokrát cykly komplikovanejšie. Metóda upto/downto (hore/dole po) vytvára cyklus pokračujúci až do zadanej hodnoty (vrátane):

hodnota1.upto/downto(hodnota2) do |index_cyklu|
    kód
end

Iterátor step zvyšuje index cyklu o zadanú hodnotu:

hodnota1.step(hodnota2, hodnota_kroku) do |aktualna_hodnota|
    kód
end

Presný počet cyklov vykonáva iterátor times:

 hodnota.times do
   kód
end

Break, redo a next v cykloch

Existujú 3 kľúčové slová využiteľné v súvislosti s cyklami a iterátormi: break, redo a next. Break okamžite ukončuje daný cyklus (ten, v ktorom sa nachádza). Redo opakuje iteráciu aktuálneho cyklu (bez toho aby došlo k novému vyhodnoteniu podmienky cyklu alebo prevzatiu nasledujúcej položky z nejakého iterátora) Next preskakuje na koniec aktuálnej iterácie (tkaže cyklus alebo iterátor preskočí na ďalšiu iteráciu alebo položku).

Metódy

Metódy slúžia na vykonávanie požadovaných inštrukcií a obvykle sa pripájajú na koniec premenných a konštánt bodkou (.). Napríklad:

svetlo.zapni

Použili sme metódu zapni. Metód môže byť viac za sebou:

svetlo.zapni.vypni.je_vypnute?

V tomto príklade sa najprv svetlo zapne, následne vypne a posledná metóda výstupom potvrdí, či je svetlo vypnuté. Niektoré metódy požadujú ďalšie informácie, vstupné hodnoty, pre vykonanie inštrukcií. Tieto sa nazývajú argumenty. Argumenty sa pripájajú za metódu ohraničené do zátvoriek a oddelené čiarkou:

svetlo.zapni(2, :minuta)

Metóda zapne 2. svetlo v poradí na 1 minútu. Niektoré metódy sú tzv. kernel metódy, metódy bežne používané Ruby, preto pred ne netreba pridávať bodku:

print “Nepotrebujem bodku pred metódu print.“

Okrem preddefinovaných metód si môžeme vytvoriť aj vlastné, napríklad:

def pozdrav
      puts Hello world!
end

Metódu následne zavoláme zadaním jej názvu.

Bloky

Blok je časť kódu vymedzená znakmi {} alebo slovami do a end. Možno ho poskytnúť metóde podobne ako argument. Pre tento účel slúži príkaz yield:

def pozdrav
    yield
end

pozdrav { puts Hello world! }

Výsledkom daného kódu je:

Hello world!

Príkaz yield je možné vykonať aj viackrát. Dáta možno blokom poskytovať pomocou príkazu yield, ktoré sa v bloku načítajú podobne ako agrumenty poskytnuté metóde:

def pozdrav
    yield Hello world!
end

pozdrav {slovo_jedna, slovo_dva | puts slovo_jedna +   + slovo_dva}

Triedy a jej premenné, objekty, moduly

Prístup k objektom jazyka Ruby

Jazyk Ruby ponúka 3 úrovne prístupu k metódam: Verejné metódy je možné volať z každého miesta kódu, nemajú žiadne obmedzenia. Chránené metódy možno volať iba vnútri objeku tej triedy, ktorá dané metódy definuje alebo objektov tried odvodených z danej triedy. Súktormné metódy je možné voleť len vnútri aktuálneho objektu. Ruby definuje kľúčové slová (public, protected, private), označované ako modifikátory prístupu.

Vytváranie premenných triedy

Premenné inštancií sa vytvárajú pridaním predpony @ pred ich názov. Premenné triedy sa dajú vytvoriť pripojením @@ pred názov. Takúto premennú triedy zdieľajú všetky jej inštancie, takže zmena tejto hodnoty v jednom objekte spôsobí zmenu vo všetkých objektoch danej triedy (naproti tomu premenné inštancií sú v objektoch interné).

class Ovocie
   @@pocet_ovocia = 0
   attr_accessor:farba
   def initialize(farba)
        @farba=farba
        @@pocet_ovocia += 1        
    end
end

Definovaná premenná triedy @@pocet_ovocia pri každom vytvorení nového objektu triedy Ovocie zvýši hodnotu o 1.

Vytváranie metód triedy

Triedy

Pre vytvorenie triedy slúži príkaz class:

class Ovocie	# vytvorenie novej triedy
   def initialize               # definovanie metódy initialize
        @farba=zlta
    end

    def vypis_farbu             # definovanie metódy výpis_farbu
         return @farba
    end
end

V uvedenom príklade sme vytvorili novú triedu Ovocie, v ktorej sme definovali dve metódy: initialize a vypis_farbu. Metóda vypis_farbu slúži na výpis farby ovocia – @farba je už spomínaná premenná inštancií, objekt charakterizujúci danú triedu. Metóda initialize sa automaticky volá, keď sa daná trieda použije na vytvorenie nového objektu. Initialize je špecifická metóda Ruby, nazývaná tiež konštruktor triedy - používa sa na konštrukciu nových objektov. Príklad:

class Ovocie
   def initialize(farba)
        @farba=farba
    end

    def vypis_farbu
         return @farba
    end
end
jablko = Ovocie.new(cervena)
puts Farba noveho ovocia je  + jablko.vypis_farbu

# výpisom bude:  Farba noveho ovocia je cervena.

Ako vidno z príkladu, vytvorili sme nový objekt jablko triedy Ovocie pomocou metódy new. Za metódu new sme pripojili vstupný argument farba, s ktorým následne pracuje metóda initialize pri vytváraní nového objektu. Metóda vypis_farba je nazývaná tiež prístupová metóda, pretože sa používa pre prístup k vnútorným hodnotám určitého objektu. V tomto prípade sa vypis_farba (v spojení jablko.vypis_farba) označuje za atribút. Atribút vypis_farba je čitateľný atribút objektu Ovocie, pretože prostredníctvom neho je možné čítať hodnotu premennej inštancií @farba. Vytvorenie čitateľného atribútu je možné zjednodušiť nasledovne:

class Ovocie
   attr_reader:farba
   def initialize(farba)
        @farba=farba
    end
end
jablko = Ovocie.new(cervena)
puts Farba noveho ovocia je  + jablko.farba

V príklade sme metódu vypis_farbu nahradili príkazom attr_reader, ktorý vytvorí inštanciu s názvom @farba a tiež metódu s rovnomenným názvom. Výsledok príkladu je totožný s predošlým dlhším kódom. Atribúty, ktoré nám umožňujú pristupovať a zapisovať hodnoty do vnútorných inštancií objektov, sa nazývajú zapisovateľné atribúty. Zapisovateľné atribúty sa dajú tiež vytvoriť dvoma spôsobmi: použitím prístupovej metódy nasledovanej znakom = :

def farba=(farba)
      @farba=farba
end

alebo kratšie pomocou príkazu attr_writer:

attr_writer:farba

Vytvorenie atribútu, ktorý bude čitateľný a zapisovateľný súčasne, nám umožní príkaz attr_accessor:

class Ovocie
   attr_accessor:farba
   def initialize(farba)
        @farba=farba
    end
end
jablko = Ovocie.new(cervena)
puts Farba ovocia je  + jablko.farba  #vypíše “Farba ovocia je cervena“
jablko.farba=zelena
puts Teraz je farba  + jablko.farba   #vypíše “Teraz je farba zelena“

Dedičnosť

V Ruby môžeme vytvoriť mnoho tried, pričom niektoré môžu byť základom pre tvorbu ďlaších. V takom prípade hovoríme o dedičnosti, kedy trieda vychádzajúca z inej triedy od tejto dedí všetky členy – dáta aj metódy. Pri definícii triedy Jablko, ktorá má dediť vlatnosti triedy Ovocie, ju definujeme nasledovne:

class Jablko < Ovocie
attr_accessor : druh
   def initialize (farba, druh)
    super(farba)
    @druh=druh
   end
end

V príklade je použitá špeciálna metóda super vstavaná do jazyka Ruby. Túto používame vtedy, keď chceme poskytnúť farbu konštruktoru základnej triedy.

Metódy triedy sa volajú pomocou mena danej triedy, pred jej použitím nie je potrebné vytvárať žiadny objekt. Toto je výhodné a užitočné najmä v prípadoch, keď nepotrebujeme ukladať dáta, s ktorými pracujeme, keďže v metóde triedy nemožno používať dáta inštancií .

Vytváranie modulov

Pri väčšom počte tried je užitočné zoskupovať ich do modulov. Modul sa vytvára kľúčovým slovom module. Modul s kódom možno vložiť do jedného súboru:

module Matematika
   def Matematika.sucet(cislo_jedna, cislo_dva)
       return cislo_jedna + cislo_dva
   end
end

Takýto modul uložený napríklad do súboru matematika.rb je možné použiť v iných súboroch príkazom include alebo skráteným príkazom (bez potreby zápisu prípony .rb) require:

include `matematika.rb` / require `matematika`
puts 2 + 3 =  + Matematika.sucet(2,3).to_s	      #výstup: “2 + 3 = 5“

Do modulov je možné ukladať aj triedy, ktoré môžu obsahovať vlastné metódy. K takýmto metódam vnútri tried modulov sa pristupuje pomocou operátora rozlíšenia oboru názvov jazyka Ruby (::) :

module Matematika
 class Scitac
   def Scitac.sucet(cislo_jedna, cislo_dva)
       return cislo_jedna + cislo_dva
   end
 end
end

require `matematika`
puts 2 + 3 = + Matematika::Scitac.sucet(2,3).to_s

Výsledok bude totožný ako v predošlom príklade.