Ruby on Rails díl.17, Ruby - Metody IV.

Napsal (») 19. 3. 2007 v kategorii Programování, přečteno: 1545×
obrazky/rubyonrailsn.pngIdeální webhosting pro Ruby on Rails je banan.cz.

Metody podrobněji


Prostě řečeno, metoda je také blok kódu. Ať tak nebo onak, ne jako Proces, metody nejsou svázané k místním proměnným kolem nich. Stačí ,že jsou vázané nějakým objektem a mají přístup k instancím jeho proměnných:

class Boogy
def initialize
@dix = 15
end

def arbo
puts "#{@dix} ha\n"
end
end


# incializuje instanci boogy
b = Boogy.new


# vytiskne "15 ha"
b.arbo


Užitečný styl pokud bereme v úvahu že metody posílají zprávy. Danému přijímači - objekt který má nějakou metodu definovanou, můžeme poslat tuto zprávu - voláním metody, optimálně s poskytnutím nějakých argumentů. Ve výše uvedeném příkladě,je volání arbo spojeno s posláním zprávy "arbo", bez argumentů. Ruby podporuje zprávu posílající styl přímější, včetně vysílací metody v třídě Object (která je rodič všech objektů v Ruby). Proto následující dva řádky jsou rovnocenné do volání metody arbo:

# metoda/zpráva jméno dostává jak řetěz
b.send("arbo")

# metoda/zpráva jméno dostává jak symbol
b.send(:arbo)


Všimněte si, že metody mohou také být definovány "na nejvyšší úrovni" rozsahu, vně všech tříd.

Například:

def say (neco)
puts neco
end

say "Ahoj"


Zatímco se zdá metoda jako "volně stojící", ve skutečnosti není. Když jsou metody takto definované, Ruby je tiše zastrčí do třídy Object. Ale to tak moc nevadí, a pro všechny praktické cíle může být stále viděná jako nezávislá metoda. To je mimochodem, právě to, co se nazývá "funkcí" v některých jazycích (jako C a Perl). Následující Proces je jí mnoha způsoby podobný:

say = lambda {|neco| puts neco}

say.call("Ahoj")

# stejny efekt
say["Ahoj"]


Hranaté závorky [] jsou synonymum k tomu, aby se volalo v kontextu Procesu. Metody, ať tak nebo onak, byly více všestranné než procesy a podporují velmi důležitý rys Ruby, který budu prezentovat hned po objasnění jednotlivých druhů bloků.

Bloky

Bloky jsou také silně příbuzné s Procesy a to uštědřuje nováčkům bolení hlav, protože zkoušejí dešifrovat jak se ve skutečnosti liší. Zkusím uhasit jejich nechápavost s (nadějnou,ale ne příliš vousatou) metaforou. Bloky, jsou z mého pohledu, nenarozené Procesy. Bloky jsou larvy, Procesy jsou jako hmyz. Blok sám nežije - připravuje kód na dobu kdy bude převeden na živý, a jen když je to vázané a převedením na Proces, tak pak začíná žit:

# samotny blok nemuze v Ruby zit
# toto je chyba kompilace !
{puts "Ahoj"}

# nyní je zivy, kdyz je preveden
# na Proces !
pr = lambda {puts "Ahoj"}

pr.call


Pokud je to tak, tak proč je kolem toho tolik povyku? Ne, vůbec ne.Návrhář Ruby, Matz viděl že při procházení Procesu metody (a dalších Procesů) je hezké a dovoluje funkcím na vysoké úrovni a všem druhům fantastického funkčního materiálu, se vyskytuje jeden obecný případ který stojí vysoko nad všemi dalšími případy - procházení jednoho bloku kódu k metodě které pro něj dělá něco užitečného, jako například iteraci. A jako velmi talentovaný návrhář, Matz rozhodl, že stojí to za to zdůrazňovat tento mimořádný případ, a udělá to oběma jednodušší a účinnější.

Procházení bloku k metodě

Nesporně každý programátor ,který strávil přinejmenším pár hodin s Ruby by měl znát následující příklady slávy Ruby (nebo něco velmi podobného):

10.times do |i|
print "#{i} "
end

numbers = [1, 2, 5, 6, 9, 21]

numbers.each do |x|
puts "#{x} is " + (x >= 3 ? "mnoho" : "par")
end

squares = numbers.map {|x| x * x}


(všimněte si, že do |x| ... konec je rovnocenný s { |x| ... } )

Takový kód je IMHO část toho, co dělá Ruby čistým, čtivým a báječným jazykem, kterým vskutku je. Co se stane zde v zákulisí je docela jednoduché, nebo přinejmenším může být zobrazeno ve velmi jednoduché cestě.Možná že to Ruby nerealizuje přesně cestou, kterou se to chystám popsat, protože určité optimalizace jistě hrají určité role - ale bude to dost blízké pravdě k tomu, aby to sloužilo jako metafora pro porozumění.

Kdykoli blok je připojený k volání metody, Ruby jej automaticky přeměňuje na Proces objektu, avšak jen jeden bez explicitního jména. Metoda, ať tak nebo onak, má způsob jak zpřístupnit tento Proces, přes yield. Podívejme se na následující příklad pro objasnění:

def do_twice
yield
yield
end

do_twice {puts "Hola"}


Metoda do_twice je definovaná a volaná s připojeným blokem. Ačkoli metoda explicitně nežádala o blok v jeho argumentech seznam, yield může volat blok. Toto může být implementováno ve víc explicitních cestách, používání Proces argumentu:

def do_twice(co)
co.call
co.call
end

do_twice lambda {puts "Hola"}


Toto je stejné použití jako v předchozím příkladu, ale používání bloků s yield je čisté, a lépe optimalizované od jednoho bloku je přijato do metody, najisto. Používání Proc přístupu, libovolné množství kódových bloků může být provedeno takto:

def do_twice(co1, co2, co3)
2.times do
co1.call
co2.call
co3.call
end
end

do_twice( lambda {print "Hola, "},
lambda {print "hoja "},
lambda {print "amigo\n"})


Je důležité všímat si, že mnoho lidí nemá rádo procházení bloků, a dává přednost explicitním Procesům. Jejich logický výklad je to , že blokový argument je již zahrnutý, a musí si prohlédnout celý kód metody aby viděly zda tam jsou k němu nějaké volání, aby tvořila yield tam, zatímco Proc je explicitní a může být ihned viditelný ve výchozím seznamu. Zatímco to jednoduše je věcí chutě, porozumění obou přístupů je zásadní.
Štítky: Ruby on Rails
Facebook Twitter Topčlánky.cz Linkuj.cz

Komentáře

Zobrazit: standardní | od aktivních | poslední příspěvky | všechno
Článek ještě nebyl okomentován.


Nový komentář

Téma:
Jméno:
Notif. e-mail *:
Komentář:
  [b] [obr]
Odpovězte prosím číslicemi: Součet čísel dvanáct a pět