Wydawnictwo Helion
ul. Kociuszki 1c
44-100 Gliwice
tel. 032 230 98 63
e-mail: helion@helion.pl
Ruby. Wprowadzenie
Autor: Michael Fitzgerald
T³umaczenie: Adam Jarczyk
ISBN: 978-83-246-1229-1
Tytu³ orygina³u:
Learning Ruby
Format: B5, stron: 240
Poznaj praktyczne zastosowania jêzyka Ruby
Podstawowe konstrukcje jêzyka i zasady programowania obiektowego
Operacje na tekstach, liczbach i plikach
Framework Ruby on Rails
Ruby obiektowy jêzyk programowania, wzglêdnie nowy, bo opracowany na pocz¹tku
lat 90. ubieg³ego wieku, zdobywa coraz wiêksz¹ popularnoæ. W zakresie tworzenia
aplikacji internetowych staje siê powa¿n¹ konkurencj¹ dla Perla, PHP i Javy.
Jest niezwykle elastyczny, posiada prost¹ sk³adniê i spore mo¿liwoci, a tworzony
w nim kod jest bardzo zwarty. Za pomoc¹ Ruby mo¿na pisaæ zarówno proste skrypty
administracyjne, jak i rozbudowane aplikacje internetowe. W budowaniu tych ostatnich
niezwykle pomocny jest framework Ruby on Rails, dziêki któremu proces tworzenia
aplikacji przebiega b³yskawicznie.
Ksi¹¿ka
Ruby. Wprowadzenie
to podrêcznik dla tych, którzy chc¹ poznaæ mo¿liwoci
jêzyka bez koniecznoci studiowania zawi³ych opisów teoretycznych. Przedstawia Ruby
na praktycznych przyk³adach, pokazuj¹c jego zastosowania w typowych zadaniach,
z jakimi spotyka siê na co dzieñ programista aplikacji sieciowych. Czytaj¹c tê ksi¹¿kê,
poznasz elementy jêzyka Ruby i nauczysz siê programowaæ obiektowo. Dowiesz siê,
w jaki sposób przetwarzaæ dane liczbowe, teksty i tablice, pliki i katalogi
oraz dokumenty XML. Przeczytasz tak¿e o rodowisku Ruby on Rails.
Instalacja jêzyka Ruby w ró¿nych systemach operacyjnych
Instrukcje i operatory
Przetwarzanie tekstów i operacje matematyczne
Operacje na systemie plików
Korzystanie z plików XML
Programowanie obiektowe
Wprowadzenie do Ruby on Raili
Wejd do wiata Ruby, a pokochasz jego mo¿liwoci!
Spis tre
ļci
_
5
Spis tre
ļci
Przedmowa ................................................................................................................................9
1. Podstawy j
ýzyka Ruby .................................................................................................. 13
Witaj, Matz!
14
Interactive Ruby
22
Zasoby
24
Instalowanie jözyka Ruby
25
Permission Denied
30
Kojarzenie typów plików w systemie Windows
30
Pytania sprawdzajñce
32
2. Krótka wycieczka po j
ýzyku Ruby ...............................................................................33
Ruby jest jözykiem obiektowym
33
Säowa zastrzeĔone jözyka Ruby
35
Komentarze
37
Zmienne
37
ãaþcuchy
40
Liczby i operatory
42
Instrukcje warunkowe
43
Tablice i tablice asocjacyjne
43
Metody
44
Bloki
48
Symbole
52
Obsäuga wyjñtków
52
Dokumentacja jözyka Ruby
53
Pytania sprawdzajñce
53
3. Instrukcje warunkowe ..................................................................................................55
Instrukcja if
55
Instrukcja case
58
6
_
Spis tre
ļci
Pötla while
59
Metoda loop
62
Pötla for
63
Wykonanie przed lub po programie
65
Pytania sprawdzajñce
66
4.
Ĥaħcuchy ........................................................................................................................67
Tworzenie äaþcuchów
67
Konkatenacja äaþcuchów
70
Dostöp do äaþcuchów
70
Porównywanie äaþcuchów
72
Manipulowanie äaþcuchami
73
Konwersja wielkoĈci liter
76
Odstöpy itp.
78
Inkrementowanie äaþcuchów
79
Konwersja äaþcuchów
80
WyraĔenia regularne
81
Ruby 1.9 i nastöpne
84
Pytania sprawdzajñce
84
5. Matematyka ..................................................................................................................85
Hierarchia klas i moduäy wbudowane
86
Konwersja liczb
86
Podstawowe operacje matematyczne
87
Zakresy
90
Zapytania o liczby
91
Inne metody matematyczne
93
Funkcje matematyczne
93
Liczby wymierne
94
Liczby pierwsze
96
Pytania sprawdzajñce
97
6. Tablice ............................................................................................................................99
Tworzenie tablic
100
Dostöp do elementów
102
Konkatenacja
104
Operacje na zbiorach
104
Elementy unikatowe
105
Na stos
105
Porównywanie tablic
105
Modyfikacja elementów
106
Usuwanie elementów
107
Spis tre
ļci
_
7
Tablice i bloki
108
Sortowanie i w tyä zwrot
108
Tablice wielowymiarowe
109
Ruby 1.9 i nastöpne
109
Inne metody klasy Array
109
Pytania sprawdzajñce
110
7. Tablice asocjacyjne ...................................................................................................... 111
Tworzenie tablicy asocjacyjnej
111
Dostöp do tablicy asocjacyjnej
112
Iteracja na tablicy asocjacyjnej
113
Modyfikacje tablicy asocjacyjnej
114
Konwersja tablicy asocjacyjnej na innñ klasö
116
Ruby 1.9 i nastöpne
117
Inne metody klasy Hash
117
Pytania sprawdzajñce
117
8. Praca z plikami .............................................................................................................119
Katalogi
119
Tworzenie nowego pliku
121
Otwieranie istniejñcego pliku
121
Usuwanie i zmiana nazw plików
124
Zapytania o pliki
124
Zmiana trybu i wäaĈciciela pliku
125
Klasa IO
126
Pytania sprawdzajñce
127
9. Klasy ............................................................................................................................. 129
Definiowanie klasy
130
Zmienne instancji
131
Akcesory
132
Zmienne klasy
134
Metody klasy
134
Dziedziczenie
136
Moduäy
137
Metody public, private i protected
139
Pytania sprawdzajñce
140
10. Dalsza zabawa z j
ýzykiem Ruby ................................................................................ 141
Formatowanie wyjĈcia za pomocñ metody sprintf
141
Przetwarzanie dokumentów XML
144
Data i czas
148
8
_
Spis tre
ļci
Refleksja
152
Tk
155
Metaprogramowanie
157
RubyGems
158
Obsäuga wyjñtków
162
Tworzenie dokumentacji za pomocñ RDoc
163
Embedded Ruby
170
Pytania sprawdzajñce
172
11. Krótki przewodnik po Ruby on Rails ......................................................................... 173
Skñd pochodzi Rails?
173
Dlaczego Rails?
174
Co inni zdziaäali z pomocñ Rails?
178
Hosting dla Rails
179
Instalowanie Rails
179
Nauka Rails
183
Krótki samouczek
184
Pytania sprawdzajñce
188
A Leksykon j
ýzyka Ruby ..................................................................................................191
B Odpowiedzi na pytania sprawdzaj
éce ......................................................................209
S
ĥowniczek ............................................................................................................................. 215
Skorowidz ..............................................................................................................................223
33
ROZDZIA
Ĥ 2.
Krótka wycieczka po j
ýzyku Ruby
Niniejszy rozdziaä przedstawia, bez zbytniego zagäöbiania siö w szczegóäy, podstawy jözyka
Ruby: klasy i moduäy, w tym klasö
Object
i moduä
Kernel
, säowa zastrzeĔone (inaczej säowa
kluczowe), komentarze, zmienne, metody i tak dalej. WiökszoĈè z tych zagadnieþ bödzie omó-
wiona bardziej szczegóäowo w innych rozdziaäach. Niektóre tematy zasäugujñ na caäe rozdziaäy,
inne tylko na podrozdziaäy (zawarte w rozdziale 10.). Za kaĔdym razem powiem, gdzie znajdujñ
siö dodatkowe informacje na dany temat. W niniejszym rozdziale zostaäy zawarte najbardziej
szczegóäowe opisy metod i bloków.
Ruby jest j
ýzykiem obiektowym
Matz, twórca jözyka Ruby, juĔ w szkole Ĉredniej marzyä o stworzeniu wäasnego jözyka progra-
mowania. Chciaä utworzyè jözyk skryptowy, który zarazem byäby zorientowany obiektowo.
Ruby wykracza poza proste pisanie skryptów, mimo Ĕe programy w nim mogñ sprawiaè wra-
Ĕenie zwykäych skryptów powäoki. Nie jest to zaledwie jözyk proceduralny, choè moĔe byè
jako taki wykorzystany.
Jözyk Ruby zawiera klasy. Klasy zawierajñ dane — w postaci staäych i zmiennych — oraz
metody, które sñ krótkimi fragmentami kodu, pomagajñcymi wykonywaè operacje na danych.
Klasy mogñ dziedziczyè po sobie informacje, lecz tylko z jednej klasy na raz. Pozwala to ponow-
nie wykorzystywaè kod — co oznacza mniej czasu zmarnowanego na naprawianie kodu i usu-
wanie z niego bäödów — oraz mieszaè ze sobñ kod poprzez dziedziczenie.
Klasa jest czymĈ w rodzaju „schematu”; za pomocñ metody
new
schemat ten moĔna przypisaè
do zmiennej lub wykonaè jego kopiö, która przez to staje siö obiektem. W jözyku Ruby
obiektem jest prawie wszystko; w istocie to, co Ruby moĔe skojarzyè z nazwñ zmiennej, jest
zawsze obiektem.
O klasach moĔna powiedzieè o wiele wiöcej; Czytelnik znajdzie mnóstwo dodatkowych infor-
macji na ich temat w rozdziale 9. Na razie wystarczñ nam podstawy. Listing 2.1 przedstawia
program w Ruby (friendly.rb) zawierajñcy dwie klasy:
Hello
i
Goodbye
. Program ten jest
zawarty w archiwum kodu Ruby towarzyszñcym niniejszej ksiñĔce (dostöpnym pod adresem
ftp://ftp.helion.pl/przyklady/rubwpr.zip). Proponujö uruchomiè program w powäoce lub wierszu
poleceþ w katalogu, do którego zostaäo rozpakowane archiwum. W przypadkach gdy przykäad
kodu nie znajduje siö w pliku, moĔna wpisaè go w irb. Zachöcam Czytelnika do wypróbowy-
wania kodu tak czösto, jak to moĔliwe.
34
_
Rozdzia
ĥ 2. Krótka wycieczka po jýzyku Ruby
Listing 2.1. friendly.rb
class Hello
def howdy
greeting = "Witaj, Matz!"
puts greeting
end
end
class Goodbye < Hello
def solong
farewell = "Do widzenia, Matz."
puts farewell
end
end
friendly = Goodbye.new
friendly.howdy
friendly.solong
Po uruchomieniu tego programu zostanñ wyĈwietlone komunikaty:
$ friendly.rb
Witaj, Matz!
Do widzenia, Matz.
DoĈwiadczeni programiĈci zapewne bez podpowiedzi zorientujñ siö, jak dziaäa kod z listingu
2.1. Czytelnicy tacy mogñ przejĈè do nastöpnego punktu (lub prosto do rozdziaäu 9., aby poznaè
caäñ kwestiö klas w jözyku Ruby).
Klasa
Hello
definiuje metodö
howdy
. Metoda ta wyĈwietla zawartoĈè äaþcucha zawartego
w zmiennej
greeting
(
Witaj, Matz!
). Klasa
Goodbye
podobnie zawiera definicjö metody
solong
,
która wyĈwietla äaþcuch przypisany do zmiennej
farewell
(
Do widzenia, Matz.
). Klasa
Good-
bye
dziedziczy teĔ zawartoĈè klasy
Hello
; do tego säuĔy tutaj operator
<
. Oznacza to, Ĕe w klasie
Goodbye
nie trzeba ponownie definiowaè metody
howdy
. Zostaäa po prostu odziedziczona.
friendly
jest obiektem, egzemplarzem klasy
Goodbye
. Metoda
new
wywoäywana z
Goodbye
pochodzi z klasy
Object
i tworzy nowy egzemplarz
friendly
(wiöcej na temat klasy
Object
w nastöpnym punkcie). MogliĈmy uĔyè obiektu
friendly
do wywoäania zarówno metody
howdy
,
jak i
solong
, poniewaĔ obie sñ dostöpne w tym obiekcie. Metoda
solong
zostaäa zdefiniowana
w klasie
Goodbye
, a metoda
howdy
odziedziczona z
Hello
.
To wszystko, co na razie chciaäem powiedzieè na ten temat. Informacje o klasach znajdñ siö
w róĔnych miejscach nastöpnych rozdziaäów. W rozdziale 9. omówiö klasy bardziej dokäadnie.
Klasa Object i modu
ĥ Kernel
Object
jest podstawowñ klasñ jözyka Ruby, nadrzödnñ wzglödem wszystkich pozostaäych klas
tego jözyka, i zawsze w sposób magiczny pojawia siö, gdy uruchamiamy program w Ruby. Nie
musimy niczego robiè, by w innych klasach uzyskaè dostöp do jej funkcjonalnoĈci. Jest zawsze
dla nas dostöpna.
Klasa
Object
zawiera bogatñ funkcjonalnoĈè w postaci metod i staäych, którñ wszystkie pro-
gramy w Ruby dziedziczñ automatycznie. W niniejszym punkcie przedstawiö czöĈè tej funk-
cjonalnoĈci.
S
ĥowa zastrzeżone jýzyka Ruby
_
35
Klasa — analogia do wiadra
Czytelnicy, którzy nie wiedzñ, na czym polega obiektowoĈè jözyka programowania, mogñ
posäuĔyè siö prostñ analogiñ. WyobraĒmy sobie klasö — podstawowy skäadnik jözyka obiekto-
wego — jako wiadro. W wiadrze znajduje siö woda i jeden lub wiöcej czerpaków. Woda to od-
powiednik wäaĈciwoĈci (danych lub informacji) mieszczñcych siö w klasie, a czerpaki sñ narzö-
dziami (metodami) do manipulowania wodñ (danymi). Podstawowym narzödziem uĔywanym
z klasami jest metoda — porcja kodu, której moĔemy nadaè nazwö i wielokrotnie jñ wy-
korzystywaè. Metoda przypomina czerpak, który zanurzamy w wiadrze i wybieramy wodö
lub nalewamy jñ. MoĔemy wiadro wykorzystaè ponownie, wylaè starñ wodö, nalaè ĈwieĔej,
a nawet wäoĔyè jedno wiadro do drugiego. Tak, bez zagäöbiania siö w Ĕargon techniczny, wy-
glñdajñ podstawy programowania obiektowego. Sporñ porcjñ Ĕargonu poczöstuje Czytelnika
rozdziaä 9.
Object
udostöpnia metody takie, jak
==
i
eql?
,
class
,
inspect
,
object_id
oraz
to_s
. Zostanñ
one dokäadniej opisane w nastöpnych rozdziaäach. Wiöcej informacji o wszystkich metodach
klasy
Object
moĔna znaleĒè pod adresem http://www.ruby-doc.org/core/classes/Object.html.
Kernel
jest moduäem jözyka Ruby. Moduä przypomina klasö, lecz nie moĔna utworzyè jego
egzemplarza, tak jak w przypadku klasy. JeĈli jednak doäñczymy moduä do klasy lub wmie-
szamy go w niñ, w obröbie tej klasy uzyskamy dostöp do wszystkich jego metod. MoĔemy uĔy-
waè metod z doäñczonego moduäu bez potrzeby ich implementowania.
Klasa
Object
zawiera moduä
Kernel
. PoniewaĔ zawsze mamy w programach Ruby dostöp
do klasy
Object
, oznacza to, Ĕe zawsze uzyskujemy dostöp równieĔ do wszystkich metod
moduäu
Kernel
. Kilka z tych metod widzieliĈmy juĔ w dziaäaniu, na przykäad
i
puts
.
Do najczöĈciej uĔywanych metod moduäu
Kernel
naleĔñ
eval
,
exit
,
gets
,
loop
,
require
,
sleep
i
sprintf
. W dalszych rozdziaäach skorzystamy z wiökszoĈci tych metod.
Nazwy metody moduäu
Kernel
nie trzeba poprzedzaè nazwñ obiektu lub odbiornika. Wystarczy
wywoäaè metodö w dowolnym miejscu programu. Wiöcej informacji o module
Kernel
moĔna
znaleĒè pod adresem http://www.ruby-doc.org/core/classes/Kernel.html.
S
ĥowa zastrzeżone jýzyka Ruby
KaĔdy jözyk programowania ma wäasnñ listö säów zastrzeĔonych (inaczej säów kluczowych),
które zarezerwowane sñ na potrzeby dziaäania jözyka. Säowami takimi sñ instrukcje w progra-
mach, a jak bez instrukcji mielibyĈmy poinformowaè komputer, co ma robiè?
Tabela 2.1 przedstawia listö säów zastrzeĔonych jözyka Ruby wraz z krótkim opisem przezna-
czenia kaĔdego z nich.
36
_
Rozdzia
ĥ 2. Krótka wycieczka po jýzyku Ruby
Tabela 2.1. S
äowa zastrzeĔone jözyka Ruby
S
ĥowo zastrzeżone
Opis
BEGIN
Kod zamkni
ýty w nawiasy klamrowe
{}
wykonywany przed samym programem.
END
Kod zamkni
ýty w nawiasy klamrowe
{}
wykonywany po zako
ħczeniu dziaĥania programu.
alias
Tworzy alias dla istniej
écej metody, operatora lub zmiennej globalnej.
and
Operator logiczny; taki sam jak
&&
, lecz o ni
ższym priorytecie (analogicznie jak
or
).
begin
Zaczyna blok kodu (grup
ý instrukcji) zakoħczony sĥowem kluczowym
end
.
break
Wychodzi z p
ýtli
while
lub
until
albo z metody wewn
étrz bloku.
case
Porównuje wyra
żenie z warunkiem
when
; instrukcja zako
ħczona przez
end
(zobacz
when
).
class
Definiuje klas
ý; definicja jest koħczona przez
end
.
def
Definiuje metod
ý; definicja jest koħczona przez
end
.
defined?
Operator specjalny sprawdzaj
écy, czy zmienna, metoda, metoda klasy bazowej lub blok istnieje.
do
Zaczyna blok i wykonuje jego zawarto
ļë, koħczy siý na
end
.
else
Wykonuje nast
ýpujécy po nim kod, jeļli poprzedni warunek (
if
,
elsif
,
unless
albo
when
)
nie jest prawdziwy.
elsif
Wykonuje nast
ýpujécy po nim kod, jeļli poprzedni warunek (
if
albo
elsif
) nie jest prawdziwy.
end
Ko
ħczy blok kodu rozpoczýty przez
begin
,
def
,
do
,
if
itp.
ensure
Zawsze wykonuje kod po zako
ħczeniu bloku; należy użyë po ostatnim
rescue
.
false
Warto
ļë logiczna (boolowska) „faĥsz”; egzemplarz klasy
FalseClass
(zobacz
true
).
for
Rozpoczyna p
ýtlý
for
; u
żywane ze sĥowem kluczowym
in
.
if
Wykonuje blok kodu, je
ļli warunek jest prawdziwy. Blok jest zakoħczony przez
end
(porównaj
z
unless
,
until
).
in
U
żywane w pýtli
for
(zobacz
for
).
module
Definiuje modu
ĥ; definicja jest koħczona przez
end
.
next
Wykonuje skok przed instrukcj
é warunkowé pýtli (porównaj z
redo
).
nil
Warto
ļë pusta, niezainicjowana zmienna, niepoprawna, lecz nie to samo co zero. Obiekt z klasy
NilClass
.
not
Operator logiczny, taki sam jak
!
.
or
Operator logiczny; taki sam jak
||
, lecz o ni
ższym priorytecie (analogicznie jak
and
).
redo
Skok po instrukcji warunkowej p
ýtli (porównaj z
next
).
rescue
Ewaluuje wyra
żenie po pojawieniu siý wyjétku; używane przed
ensure
.
retry
Na zewn
étrz
rescue
powtarza wywo
ĥanie metody; wewnétrz
rescue
wykonuje skok na pocz
étek
bloku (
begin
).
return
Zwraca warto
ļë z metody lub bloku. Można pominéë.
self
Obiekt bie
żécy (wywoĥane przez metodý).
super
Wywo
ĥuje metodý o tej samej nazwie w superklasie (klasie nadrzýdnej wzglýdem bieżécej).
then
Kontynuacja instrukcji
if
,
unless
lub
when
. Mo
żna pominéë.
true
Warto
ļë logiczna (boolowska) „prawda”; egzemplarz klasy
TrueClass
(zobacz
false
).
undef
Usuwa definicj
ý metody w bieżécej klasie.
unless
Wykonuje blok kodu, je
ļli instrukcja warunkowa zwróci
false
(porównaj z
if
,
until
).
until
Wykonuje blok kodu, gdy instrukcja warunkowa zwróci
false
(porównaj z
if
,
unless
).
when
Rozpoczyna klauzul
ý (jedné lub wiýcej) po
case
.
Zmienne
_
37
Tabela 2.1. S
äowa zastrzeĔone jözyka Ruby — ciñg dalszy
S
ĥowo zastrzeżone
Opis
while
Wykonuje blok kodu, je
ļli instrukcja warunkowa zwróci
true
.
yield
Wykonuje blok przekazany do metody.
__FILE__
Nazwa bie
żécego pliku Śródĥowego.
__LINE__
Numer bie
żécego wiersza w bieżécym pliku Śródĥowym.
Komentarze
Komentarz ukrywa wiersze skryptu przed interpreterem jözyka Ruby, tak Ĕe zostajñ odrzucone
(zignorowane). UmoĔliwia to programistom (czyli nam) wstawianie do programów wszelkiego
rodzaju informacji, które pozwolñ innym uĔytkownikom zorientowaè siö, o co chodzi. W Ruby
stosowane sñ dwa podstawowe style komentarzy. Symbol
#
(hash) moĔe znajdowaè siö na
poczñtku wiersza:
# Jestem tylko komentarzem. Nie zwracaj na mnie uwagi.
albo po instrukcji lub wyraĔeniu, w tym samym wierszu:
name = "Floydee Wallup" # te
Ī mi nazwisko…
Komentarz moĔe zajmowaè kilka wierszy pod rzñd:
# To jest komentarz.
# To te
Ī jest komentarz.
# I to te
Ī jest komentarz.
# Nie b
ĊdĊ siĊ powtarzaü.
Oto inna forma: blokowy komentarz, który ukrywa przed interpreterem kilka wierszy pomiödzy
säowami kluczowymi
=begin
i
=end
:
=begin
To jest komentarz.
To te
Ī jest komentarz.
I to te
Ī jest komentarz.
Nie b
ĊdĊ siĊ powtarzaü.
=end
W ten sposób moĔna zakomentowaè jeden wiersz lub dowolnñ ich liczbö.
Zmienne
Zmienna jest identyfikatorem (nazwñ), któremu moĔna przypisaè wartoĈè. Podczas dziaäania
programu wartoĈè ma lub bödzie mieè okreĈlony typ. W poniĔszym przykäadzie zmiennej
x
zostaje za pomocñ znaku równoĈci przypisana wartoĈè 100:
x = 100
Teraz zmienna lokalna
x
zawiera wartoĈè 100. Ale jakiego typu? Dla mnie wyglñda na liczbö
caäkowitñ, a dla Czytelnika? A jak zinterpretuje jñ Ruby?
Wiele wspóäczesnych jözyków programowania, na przykäad C++ i Java, stosuje statycznñ
kontrolö typu. Oznacza to, Ĕe zmiennej w chwili jej deklarowania przypisuje siö okreĈlony typ,
a poniewaĔ w jözykach tych kontrola typów jest Ĉcisäa, zmienna zachowuje typ, dopóki nie
zostanie jej przypisany inny (o ile jest to w ogóle moĔliwe).
38
_
Rozdzia
ĥ 2. Krótka wycieczka po jýzyku Ruby
Na przykäad, w jözyku Java zmienne deklaruje siö z podaniem typu (
int
) po lewej stronie:
int months = 12;
int year = 2007;
W jözyku Ruby nie ma deklaracji typów. WartoĈci sñ po prostu przypisywane do zmiennych:
months = 12
year = 2007
JeĈli ktoĈ sobie tego Ĕyczy, moĔe zakoþczyè wiersz Ĉrednikiem, lecz znak koþca wiersza w zupeä-
noĈci wystarczy.
WartoĈci w zmiennych
x
,
months
i
year
sñ ewidentnie liczbami caäkowitymi (integer), lecz nie
musimy wskazywaè typu, poniewaĔ Ruby robi to za nas automatycznie. Nosi to nazwö dyna-
micznej kontroli typów lub potocznie duck typing.
Mechanizm dziaäa tak: jeĈli zauwaĔymy ptaka wodnego, który chodzi jak kaczka (ang. duck),
kwacze jak kaczka, fruwa jak kaczka i päywa jak kaczka, to, na honor, zapewne mamy do czy-
nienia z kaczkñ. Ruby podobnie sprawdza wartoĈè przypisanñ do zmiennej — jeĈli ta wartoĈè
chodzi, kwacze, fruwa i päywa jak liczba caäkowita, Ruby przyjmuje, Ĕe moĔe graè rolö liczby
caäkowitej.
Zobaczmy, czy Ruby moĔe uznaè wartoĈè
x
za liczbö caäkowitñ, za pomocñ metody
kind_of?
(jest to metoda z klasy
Object
).
x.kind_of? Integer # => true
AleĔ oczywiĈcie, wartoĈè zmiennej
x
zachowuje siö jak liczba caäkowita! W istocie jest egzem-
plarzem klasy
Fixnum
, która dziedziczy klasö
Integer
.
x.class # => Fixnum
Zmieþmy teraz wartoĈè
x
z caäkowitej na zmiennoprzecinkowñ za pomocñ metody
to_f
z klasy
Fixnum
(jest teĔ dziedziczona przez inne klasy):
x.to_f # => 100.0
Jak wspomniaäem w rozdziale 1., zapis
=>
w przykäadach kodu pojawia siö tu zawsze
po znaku komentarza (
#
). Tekst nastöpujñcy po
=>
jest wynikiem, którego moĔemy siö
spodziewaè z wiersza lub bloku kodu albo caäego programu.
Zmienne lokalne
Nazwaäem wczeĈniej
x
zmiennñ lokalnñ. Co to znaczy? Oznacza to, Ĕe zmienna ma zasiög
(kontekst) lokalny. Na przykäad, gdy zmienna lokalna zostaje zdefiniowana wewnñtrz metody
lub pötli, ma zasiög w obröbie tej metody lub pötli. Na zewnñtrz nie jest do niczego przydatna.
Nazwy zmiennych lokalnych muszñ zaczynaè siö od maäej litery lub znaku podkreĈlenia (
_
), na
przykäad
alpha
lub
_beta
. Zmienne lokalne w jözyku Ruby moĔemy teĔ poznaè po tym, Ĕe ich
nazwy nie sñ poprzedzane znakami specjalnymi, z wyjñtkiem podkreĈlenia. Istniejñ teĔ inne typy
zmiennych, z äatwoĈciñ identyfikowane przez pierwszy znak nazwy. NaleĔñ do nich zmienne
globalne, zmienne instancji i zmienne klasy.
Zmienne
_
39
Zmienne instancji
Zmienna instancji jest zmiennñ, do której odwoäujemy siö przez wystñpienie (egzemplarz) kla-
sy, wiöc naleĔy do okreĈlonego obiektu. Nazwy takich zmiennych poprzedza znak
@
:
@hello = hello
Dostöp do zmiennej instancji spoza jej wäasnej klasy jest moĔliwy tylko przez metody akcesora.
Wiöcej informacji o tych metodach zawiera rozdziaä 9.
Zmienne klasy
Zmienna klasy jest wspóäuĔytkowana przez wszystkie wystñpienia klasy. Dla danej klasy
istnieje tylko jedna kopia zmiennej klasy. W jözyku Ruby nazwy zmiennych tego typu poprze-
dzajñ dwa znaki
@
(
@@
). Przed uĔyciem zmiennej klasy naleĔy jñ zainicjalizowaè (przypisaè
wartoĈè):
@@times = 0
Zmienne klasy zobaczymy w akcji w rozdziale 9.
Zmienne globalne
Zmienne globalne sñ dostöpne globalnie w caäym programie, w kaĔdej jego strukturze. Ich
zasiögiem jest caäy program. Nazwö zmiennej globalnej poprzedza symbol dolara (
$
):
$amount = "0.00"
Trudno jest Ĉledziè wykorzystanie zmiennych globalnych. Lepiej wyjdziemy na projektowaniu
kodu tak, by wykorzystywaä zmienne klasy i staäe. Matz twierdzi, cytujö, Ĕe zmienne globalne
„sñ paskudne, wiöc nie korzystaj z nich”. Sñdzö, Ĕe to dobra rada (lepiej uĔywaè metod singleton;
zobacz rozdziaä 9.).
Sta
ĥe
Staäa mieĈci niezmiennñ wartoĈè przez caäy czas dziaäania programu w Ruby. Staäe sñ zmien-
nymi, których nazwy zaczynajñ siö od duĔej litery lub sñ zapisane samymi duĔymi literami.
Oto definicja staäej o nazwie
Matz
:
Matz = "Yukishiro Matsumoto"
puts Matz # => Yukishiro Matsumoto
JeĈli staäa zostaäa zdefiniowana wewnñtrz klasy lub moduäu, bödzie dostöpna w tej klasie lub
module; jeĈli zdefiniujemy jñ na zewnñtrz klas i moduäów, bödzie dostöpna globalnie. W prze-
ciwieþstwie do innych jözyków w Ruby staäe sñ zmienialne (mutable) — inaczej mówiñc, moĔna
modyfikowaè ich wartoĈci.
Przypisanie równoleg
ĥe
Podoba mi siö w jözyku Ruby moĔliwoĈè przypisywania równolegäego (jak w jözykach Perl,
Python i JavaScript 1.7). Co to takiego? Jest to sposób przypisywania w jednej instrukcji kilku
zmiennych, w jednym wierszu. Czösto przypisujemy po jednej zmiennej na wiersz:
40
_
Rozdzia
ĥ 2. Krótka wycieczka po jýzyku Ruby
x = 100
y = 200
z = 500
W przypisaniu równolegäym moĔemy uzyskaè ten sam efekt, oddzielajñc od siebie nazwy zmien-
nych, a nastöpnie wartoĈci przecinkami:
x, y, z = 100, 200, 500
MoĔliwe jest nawet przypisanie wartoĈci róĔnych typów, na przykäad äaþcucha, wartoĈci zmien-
noprzecinkowej i caäkowitej:
a, b, c = "cash", 1.99, 100
Przypisanie równolegäe jest wygodne. To bardzo typowe dla jözyka Ruby.
Ĥaħcuchy
ãaþcuch jest ciñgiem liter, cyfr i innych znaków. W jözyku Ruby istnieje kilka metod tworzenia
äaþcuchów, lecz najprostszñ chyba jest zapisanie tekstu w cudzysäowach (mogñ byè pojedyncze
lub podwójne). WeĒmy cytat z ksiñĔki Walden Henry Davida Thoreau:
thoreau = "Dobro
ð jest jedynî inwestycjî, która nigdy nie zawodzi."
1
Metody klasy
String
pozwalajñ uzyskaè dostöp do äaþcucha
thoreau
i manipulowaè nim.
MoĔemy, na przykäad, pobraè fragment äaþcucha za pomocñ metody
[]
, uĔywajñc zakresu.
WeĒmy znaki z pozycji od 33. do 37.:
thoreau[33..37] # => "nigdy"
Albo, zaczynajñc od koþca äaþcucha i uĔywajñc liczb ujemnych, weĒmy znaki od przedostatniego
do ósmego od koþca:
thoreau[-8..-2] # => "zawodzi"
MoĔemy przejĈè iteracyjnie przez wszystkie znaki äaþcucha, uĔywajñc bloku kodu, który pobierze
kolejno kaĔdy bajt (8 kolejnych bitów) äaþcucha i wygeneruje z niego znak za pomocñ metody
chr
, oddzielajñc od siebie kolejne znaki ukoĈnikami:
thoreau.each_byte do |c|
print.chr, "/"
end
# => D/o/b/r/o/
ü/ /j/e/s/t/ /j/e/d/y/n/ą/ /i/n/w/e/s/t/y/c/j/ą/,/ /k/t/ó/r/a/ /n/i/g/d/y/ /n/i/e/ /z/a/w/o/d/z/i/./
Niniejsza wskazówka przeznaczona jest dla czytelników, którzy chcñ w programach
uĔywaè nie tylko znaków ASCII; w przeciwnym razie moĔe byè nadmiarem informacji.
Muszö przyznaè, Ĕe zaäoĔenie, iĔ znak jest równowaĔny bajtowi, jest doĈè staroĈwieckie.
W szerszym kontekĈcie (w Unicode) znak moĔe byè reprezentowany przez wiöcej niĔ
jeden bajt. Na przykäad, w kodowaniu UTF-8 kaĔdy znak jest reprezentowany przez
od jednego do czterech bajtów. Ruby domyĈlnie stosuje kodowanie znaków ASCII,
lecz moĔemy to zmieniè, ustawiajñc (w okolicach poczñtku programu) w zmiennej
$KCODE
wartoĈè
u
(dla UTF-8),
e
(dla EUC),
s
(dla SJIS),
a
(ASCII) lub
n
(
NONE
).
1
Täumaczenie wäasne — przyp. täum.
Ĥaħcuchy
_
41
Tak przy okazji, metoda
chr
konwertuje kod znaku (wygenerowany przez
each_byte
) na
faktyczny znak. Powinienem teĔ wspomnieè o metodzie odwrotnej — operatorze
?
, który
zwraca kod podanego znaku. Zademonstrujö to w irb:
irb(main):001.0> ?I
=> 73
irb(main):002.0> ?f
=> 102
irb(main):003.0> ?\ # nie wida
ü znaku, ale tu jest spacja
=> 32
irb(main):004.0> ?m
=> 109
irb(main):005.0> ?a
=> 97
irb(main):006.0> ?n
=> 110
Nie bödö siö tu zbytnio zagäöbiaè w szczegóäy; wiöcej informacji o äaþcuchach zawiera rozdziaä 4.
Wyra
żenia regularne
WyraĔenie regularne jest specjalnym ciñgiem znaków, który dopasowuje äaþcuch lub zbiór
äaþcuchów. WyraĔenia regularne (potocznie „regexp” od regular expression) czösto sñ wykorzy-
stywane do znajdowania pasujñcych äaþcuchów, aby póĒniej zrobiè coĈ z nimi lub wykonaè innñ
operacjö. SäuĔñ teĔ do pobierania äaþcuchów lub podäaþcuchów do wykorzystania gdzieĈ indziej.
WyraĔenia regularne skäadajñ siö z elementów (jednego lub wiöcej znaków), które instruujñ
silnik wyraĔeþ regularnych, jakie äaþcuchy ma wyszukiwaè. Na wzorzec wyraĔenia regular-
nego skäada siö kombinacja znaków specjalnych zawarta w ukoĈnikach (
//
). Oto kilka przy-
käadów:
^
Dopasowuje poczñtek wiersza.
$
Dopasowuje koniec wiersza.
\w
Dopasowuje säowo (dowolnñ kombinacjö liter i cyfr).
[...]
Dopasowuje dowolny znak w nawiasach prostokñtnych.
[^...]
Dopasowuje dowolny znak, który nie znajduje siö w nawiasach prostokñtnych.
*
Dopasowuje zero lub wiöcej wystñpieþ poprzedniego wyraĔenia regularnego.
+
Dopasowuje jedno lub wiöcej wystñpieþ poprzedniego wyraĔenia regularnego.
?
Dopasowuje zero lub jedno wystñpienie poprzedniego wyraĔenia regularnego.
42
_
Rozdzia
ĥ 2. Krótka wycieczka po jýzyku Ruby
Oto przykäad wyraĔenia regularnego dopasowujñcego äaþcuchy za pomocñ metody
scan
z klasy
String
:
hamlet = "Znosi
ð pociski zawistnego losu"
hamlet.scan(/\w+/) # => ["Znosi
ü", "pociski", "zawistnego", "losu"]
Dopasowuje ono jedno lub wiöcej (
+
) säów (
\w
) i umieszcza znalezione wyniki w tablicy.
W szczegóäy wyraĔeþ regularnych zagäöbiö siö w rozdziale 4. Znajduje siö w nim tabela wszyst-
kich wzorców wyraĔeþ regularnych rozpoznawanych przez jözyk Ruby. Czytelników powaĔ-
nie zainteresowanych tym tematem odsyäam do ksiñĔki Jeffreya E. F. Friedla WyraĔenia regularne
(Helion, Gliwice 2001).
Liczby i operatory
W wiökszoĈci obiektowych jözyków programowania liczby sñ uznawane za podstawowe ele-
menty skäadowe nazywane prymitywami lub elementami pierwotnymi. Nie sñ wprost powiñ-
zane z Ĕadnñ klasñ; po prostu sñ. W jözyku Ruby jest inaczej: nawet liczby sñ egzemplarzami klas.
Dodatnia liczba caäkowita 1001, na przykäad, jest egzemplarzem klasy
Fixnum
, która jest klasñ
potomnñ klasy
Integer
, a ta z kolei potomnñ klasy
Numeric
. Zmiennoprzecinkowa liczba 1001.0
jest egzemplarzem klasy
Float
, która równieĔ jest klasñ potomnñ
Numeric
(rysunek 5.1 przed-
stawia relacje pomiödzy tymi klasami).
Wraz z liczbami pojawiajñ siö operacje, które na tych liczbach moĔna wykonywaè. MoĔemy je,
na przykäad, dodawaè, dzieliè, mnoĔyè, podnosiè do potögi czy teĔ zwracaè resztö z dzielenia
(modulo).
Doskonaäym narzödziem do zaznajomienia siö z dziaäaniami matematycznymi w Ruby jest irb.
Wypróbujmy kilka z nich:
irb(main):001.0> 3 + 4 # dodawanie
=> 7
irb(main):002.0> 7 - 3 # odejmowanie
=> 4
irb(main):003.0> 3 * 4 # mno
Īenie
=> 12
irb(main):004.0> 12 / 4 # dzielenie
=> 3
irb(main):005.0> 12**2 # podniesienie do pot
Ċgi
=> 144
irb(main):006.0> 12 % 7 # modulo (reszta)
=> 5
Oto kilka operatorów przypisania jözyka Ruby w akcji:
irb(main):007.0> x = 12 # przypisanie
=> 12
irb(main):008.0> x += 1 # skrócony zapis przypisania z dodaniem
=> 13
irb(main):009.0> x -= 1 # skrócony zapis przypisania z odejmowaniem
=> 12
irb(main):010.0> x *= 2 # skrócony zapis przypisania z mno
Īeniem
=> 3
irb(main):011.0> x /= 2 # skrócony zapis przypisania z dzieleniem
=> 144
Tablice i tablice asocjacyjne
_
43
Ruby zawiera równieĔ moduä
Math
, udostöpniajñcy wszelkiego rodzaju funkcje matematyczne
(w postaci metod klas), takie jak pierwiastek kwadratowy, cosinus, tangens i tak dalej. Oto przy-
käad wywoäania metody klasy
sqrt
(pierwiastek kwadratowy) z moduäu
Math
:
irb(main):012.0> Math.sqrt(16)
=> 4.0
Poza tym Ruby udostöpnia kilka specjalnych klas matematycznych, na przykäad
Rational
do
operacji na uäamkach. Wiöcej o liczbach i operatorach powiem w rozdziale 5. Tabela 5.1 przed-
stawia wszystkie operatory matematyczne w jözyku Ruby, äñcznie z pierwszeþstwem.
Instrukcje warunkowe
Podobnie jak kaĔdy inny jözyk programowania, Ruby zawiera instrukcje warunkowe, które
sprawdzajñ, czy okreĈlone stwierdzenie jest prawdziwe, czy faäszywe. Na podstawie odpowiedzi
jest nastöpnie wykonywany blok kodu. Oto prosty przykäad instrukcji
if
, w której sprawdzamy,
czy zmienna ma wartoĈè zero:
value = 0
if value.zero? then
puts "Zmienna value ma warto
Łð 0. DomyŁliĪeŁ siĂ tego?"
end
Metoda
zero?
zwraca
true
, jeĈli wartoĈè zmiennej
value
wynosi zero. Tak teĔ jest w naszym
przypadku, wiöc nastöpna instrukcja zostaje wykonana (wraz z wszelkimi innymi instrukcjami
w bloku kodu pomiödzy
if
a
end
). Zgodnie z konwencjñ jözyka Ruby kaĔda metoda, której
nazwa zakoþczona jest znakiem zapytania, zwraca wartoĈè boolowskñ —
true
albo
false
.
Konwencja ta nie jest jednak wymuszana.
Do innych instrukcji warunkowych naleĔñ na przykäad znane nam
case
i
while
oraz mniej
znane, jak na przykäad
until
i
unless
. Rozdziaä 3. opisuje wszystkie instrukcje warunkowe
dostöpne w jözyku Ruby.
Tablice i tablice asocjacyjne
Tablica jest uporzñdkowanñ sekwencjñ indeksowanych wartoĈci, w której indeks zaczyna siö od
zera. Stanowi jednñ z najczöĈciej spotykanych w informatyce struktur danych. W jözyku Ruby
tablica moĔe wyglñdaè tak:
pacific = ["Waszyngton", "Oregon", "Kalifornia"]
Nasza tablica ma nazwö
pacific
. Zawiera trzy äaþcuchy — nazwy trzech stanów skäadajñcych
siö na zachodnie wybrzeĔe USA. ãaþcuchy te sñ elementami tablicy. Elementami tablicy mogñ
byè, oczywiĈcie, dane dowolnego typu z jözyka Ruby, nie jedynie äaþcuchy. PowyĔszy przy-
käad jest tylko jednym ze sposobów definiowania tablicy. Istnieje wiele innych, które poznamy
w rozdziale 6.
Aby uzyskaè dostöp do wybranego elementu, moĔna podaè w metodzie jego indeks. Na przy-
käad, by pobraè pierwszy element, którego indeks ma wartoĈè zero, moĔemy uĔyè metody
[]
:
pacific[0] # => "Waszyngton"
44
_
Rozdzia
ĥ 2. Krótka wycieczka po jýzyku Ruby
Wywoäanie tej metody zwraca wartoĈè elementu zerowego — äaþcuch
Waszyngton
. Wiöcej
informacji o tablicach w jözyku Ruby zawiera rozdziaä 6.
Tablica asocjacyjna (ang. hash), która przypisuje klucze do wartoĈci, równieĔ jest powszechnie
spotykanñ strukturñ danych. W przeciwieþstwie do zwykäej tablicy, w której indeksami sñ
dodatnie liczby caäkowite, w tablicy asocjacyjnej moĔemy dowolnie wybraè klucze säuĔñce do
indeksowania. Wyglñda to tak:
pacific = { "WA" => "Waszyngton", "OR" => "Oregon", "CA" => "Kalifornia" }
Definicja tablicy asocjacyjnej jest zamkniöta w nawiasy klamrowe, natomiast zwykäej w nawiasy
prostokñtne. Poza tym kaĔda wartoĈè jest kojarzona z kluczem za pomocñ operatora
=>
. Jednñ
z metod dostöpu do wartoĈci w tablicy asocjacyjnej jest podanie klucza. Aby pobraè z naszej
tablicy asocjacyjnej wartoĈè Oregon, moĔemy uĔyè metody
[]
z klasy
Hash
:
pacific["OR"] # => "Oregon"
Podajñc klucz
OR
, otrzymaliĈmy wartoĈè
Oregon
. Klucze i wartoĈci mogñ byè dowolnego typu,
nie tylko äaþcuchami. Wiöcej informacji o tablicach asocjacyjnych zawiera rozdziaä 7.
Metody
Metody pozwalajñ zgrupowaè kod (instrukcje i wyraĔenia) w jednym miejscu, tak Ĕe moĔna go
póĒniej wygodnie wykorzystaè — jeĈli bödzie trzeba, wielokrotnie. MoĔemy definiowaè metody
wykonujñce najróĔniejsze czynnoĈci. W istocie wiökszoĈè operatorów matematycznych w jözyku
Ruby to metody.
PoniĔszy opis metod jest najbardziej zwiözäy ze wszystkich zawartych w niniejszej
ksiñĔce, wiöc Czytelnik byè moĔe zechce powracaè do niego w trakcie dalszej lektury.
Oto prosta definicja metody o nazwie
hello
, stworzona z uĔyciem säów kluczowych
def
i
end
:
def hello
puts "Witaj, Matz!"
end
Ta metoda po prostu wyĈwietla tekst za pomocñ instrukcji
puts
. Z drugiej strony, moĔemy usu-
nñè definicjö metody instrukcjñ
undef
:
undef hello # usuwamy definicj
Ċ metody o nazwie hello
hello # spróbujemy teraz wywo
áaü metodĊ
NameError: undefined local variable or method 'hello' for main:Object
from (irb):11
from :0
MoĔemy teĔ definiowaè metody majñce argumenty, jak w poniĔszym przykäadzie:
def repeat ( word, times )
puts word * times
end
repeat("Witaj! ", 3) # => Witaj! Witaj! Witaj!
repeat("
Şegnaj! ", 4) # => ĩegnaj! ĩegnaj! ĩegnaj! ĩegnaj!
Metody
_
45
Nasza metoda
repeat
przyjmuje dwa argumenty:
word
i
times
. Metodö majñcñ zdefiniowane
argumenty moĔemy wywoäywaè z nawiasami lub bez przed i po argumentach. MoĔna nawet
definiowaè argumenty metody bez nawiasów, lecz zwykle tak nie robiö.
Dziöki temu, Ĕe nawiasy nie sñ wymagane, moĔemy zapisywaè normalnie wyglñdajñce równania
matematyczne, korzystajñc z metod operatorów, na przykäad
+
. KaĔdy z trzech poniĔszych wier-
szy jest w rzeczywistoĈci poprawnym wywoäaniem metody
+
klasy
Fixnum
:
10 + 2 # => 12
10. + 2 # => 12
(10). + (2) # => 12
Warto
ļci zwracane
Metody zwrajñ wartoĈci. W innych jözykach programowania moĔemy jawnie otrzymaè zwracanñ
wartoĈè za pomocñ instrukcji
return
. W jözyku Ruby zwracana jest ostatnia wartoĈè z metody,
z uĔyciem instrukcji
return
lub bez. Taki jest styl Ruby. Oto, jak moĔemy to sprawdziè w irb:
1.
Na poczñtek zdefiniujemy metodö
matz
zawierajñcñ jedynie äaþcuch:
irb(main):001:0> def matz
irb(main):002:1> "Witaj, Matz!"
irb(main):003:1> end
=> nil
2.
Po wywoäaniu metody
matz
zobaczymy jej wyjĈcie. Jest to dostöpne w irb, lecz nie bödzie
widoczne w przypadku uruchomienia normalnego programu z wiersza zachöty powäoki.
Aby wyĈwietliè wyjĈcie, w programie uĔylibyĈmy instrukcji
puts
:
irb(main):004:0> matz
=> "Witaj, Matz!"
irb(main):005:0> puts matz
"Witaj, Matz!"
=> nil
3.
Przypiszemy teraz metodö
matz
do zmiennej
output
i wyĈwietlimy tö zmiennñ:
irb(main):006:0> output = matz
=> "Witaj, Matz!"
irb(main):007:0> puts output
"Witaj, Matz!"
=> nil
4.
JeĈli ktoĈ sobie tego zaĔyczy, moĔe uĔyè jawnie instrukcji
return
. Zdefiniujemy ponownie
metodö
matz
, tym razem dodajñc instrukcjö
return
, i otrzymamy ten sam wynik:
irb(main):008:0> def matz
irb(main):009:1> return "Witaj, Matz!"
irb(main):010:1> end
=> nil
irb(main):011:0> matz
"Witaj, Matz!"
irb(main):012:0> puts matz
"Witaj, Matz!"
=> nil
irb(main):013:0> output = matz
=> "Witaj, Matz!"
irb(main):014:0> puts output
"Witaj, Matz!"
=> nil
46
_
Rozdzia
ĥ 2. Krótka wycieczka po jýzyku Ruby
Konwencje nazewnicze metod
W jözyku Ruby stosowane sñ konwencje dotyczñce ostatniego znaku nazwy metody — konwen-
cje powszechnie stosowane, lecz nie wymuszane przez jözyk.
Gdy nazwa metody koþczy siö znakiem zapytania, na przykäad
eql?
, metoda zwraca wartoĈè
boolowskñ —
true
albo
false
. Na przykäad:
x = 1.0
y = 1.0
x.eql? y # => true
Gdy nazwa metody koþczy siö wykrzyknikiem, na przykäad
delete!
, wskazuje to, Ĕe metoda
jest „niszczycielska” — inaczej mówiñc, wprowadza zmiany w samym obiekcie, a nie w jego
kopii. Modyfikuje sam obiekt. Proszö zwróciè uwagö na róĔnice wyników dziaäania metod
delete
i
delete!
klasy
String
:
der_mensch = "Matz!" # => "Matz!"
der_mensch.delete( "!" ) = "Matz!" # => "Matz"
puts der_mensch # => "Matz!"
der_mensch.delete!( "!" ) = "Matz!" # => "Matz"
puts der_mensch # => "Matz"
Gdy nazwa metody koþczy siö znakiem równoĈci, na przykäad
family_name=
, oznacza to,
Ĕe metoda jest tzw. „setterem” — przeprowadza przypisanie lub ustawia zmiennñ, na przykäad
zmiennñ instancji w klasie:
class Name
def family_name=( family )
@family_name = family
end
def given_name=( given )
@given_name = given
end
end
n = Name.new
n.family_name= "Matsumoto" # => "Matsumoto"
n.given_name= "Yukihiro" # => "Yukihiro"
p n # => <Name:0x1d441c @family_name="Matsumoto", @given_name="Yukihiro">
W jözyku Ruby dostöpna jest bardziej praktyczna technika tworzenia metod getter/setter i akce-
sorów. Zostaäa ona opisana w rozdziale 9.
Argumenty domy
ļlne
Metoda
repeat
, przedstawiona wczeĈniej, ma dwa argumenty. MoĔemy im przypisaè wartoĈci
domyĈlne, uĔywajñc znaku równoĈci, a po nim wartoĈci. JeĈli wywoäamy metodö bez argumen-
tów, automatycznie zostanñ uĔyte wartoĈci domyĈlne.
Zdefiniujmy
repeat
ponownie, uĔywajñc wartoĈci domyĈlnych:
Witaj!
dla
word
i 3 dla
times
.
Wywoäamy teraz metodö najpierw bez argumentów, a nastöpnie z nimi.
def repeat ( word="Witaj! ", times=3 )
puts word * times
end
repeat # => Witaj! Witaj! Witaj!
repeat("
Şegnaj! ", 5 ) # => ĩegnaj! ĩegnaj! ĩegnaj! ĩegnaj! ĩegnaj!
Metody
_
47
Gdy metodö wywoäaliĈmy bez argumentów, zostaäy uĔyte wartoĈci domyĈlne; lecz gdy podali-
Ĉmy argumenty, wartoĈci domyĈlne zostaäy odrzucone i zastñpione wartoĈciami argumentów.
Zmienna liczba argumentów
Czasem nie wiemy, ile argumentów bödzie miaäa metoda. MoĔemy pozwoliè sobie na elastycz-
noĈè, poniewaĔ Ruby umoĔliwia przekazanie do metody zmiennej liczby argumentów, poprze-
dzajñc po prostu argument symbolem
*
. Listing 2.2 przedstawia prosty program, który wyko-
rzystuje tö metodö.
Listing 2.2. num_args.rb
def num_args( *args )
length = args.size
label = length == 1 ? " argument" : " arguments"
num = length.to_s + label + " ( " + args.inspect + " )"
num
end
puts num_args
puts num_args(1)
puts num_args( 100, 2.5, "three" )
W tym programie operator trójkowy (
?:
) posäuĔyä do ustalenia, czy rzeczownik
argument
powinien byè w liczbie pojedynczej, czy mnogiej (wiöcej o operatorach trójkowych w nastöpnym
rozdziale).
Gdy uĔyjemy tej skäadni dla róĔnej liczby argumentów, bödñ one zapisane w tablicy, co pozwoli
zilustrowaè metoda
inspect
. Trzy wywoäania
num_args
sñ poprzedzone instrukcjñ
puts
, aby
wysäaè wartoĈè zwracanñ metody na wyjĈcie standardowe:
0 arguments ( [] )
1 argument ( [1] )
3 arguments ( [100, 2.5, "three"] )
JednoczeĈnie z argumentami zmiennymi moĔemy uĔywaè zwykäych. Caäa sztuka polega na
tym, Ĕe zmienna lista argumentów (zaczynajñca siö od
*
) zawsze powinna znajdowaè siö na koþ-
cu listy. Listing 2.3 ilustruje metodö, która ma dwa zwykäe argumenty i miejsce na dodatkowe.
Listing 2.3. two_plus.rb
def two_plus( one, two, *args )
length = args.size
label = length == 1 ? " variable argument" : " variable arguments"
num = length.to_s + label + " (" + args.inspect + ")"
num
end
puts two_plus( 1, 2 )
puts two_plus( 1000, 3.5, 14.3 )
puts two_plus( 100, 2.5, "three", 70, 14.3 )
Oto wyjĈcie programu (ilustruje tylko liczbö argumentów zmiennych, ignorujñc zwykäe):
48
_
Rozdzia
ĥ 2. Krótka wycieczka po jýzyku Ruby
0 variable arguments ( [] )
1 variable argument ( [14.3] )
3 variable arguments ( [100, 2.5, "three"] )
Proszö spróbowaè wywoäaè
two_plus
bez Ĕadnych argumentów i sprawdziè, jaka bödzie odpo-
wiedĒ interpretera.
Aliasy metod
Jözyk Ruby zawiera säowo kluczowe
alias
, które tworzy aliasy metod. Oznacza to, Ĕe tworzy-
my kopiö metody pod nowñ nazwñ, aczkolwiek wywoäanie obu metod bödzie kierowane do
tego samego obiektu. Za pomocñ
alias
(lub metody
alias_method
klasy
Module
) moĔemy
uzyskaè dostöp do metod, które zostaäy nadpisane.
PoniĔszy przykäad z irb ilustruje, jak utworzyè alias metody
greet
:
irb(main):001:0> def greet
irb(main):002:1> puts "Cze
Ŀî, dziecinko!"
irb(main):003:1> end
=> nil
irb(main):004:0> alias baby greet # tworzymy alias greet pod nazw
ą baby
=> nil
irb(main):005:0> greet # wywo
áujemy metodĊ
Cze
Łð, dziecinko!
=> nil
irb(main):006:0> baby # wywo
áujemy alias
Cze
Łð, dziecinko!
=> nil
irb(main):007:0> greet.object_id # jaki jest identyfikator obiektu?
Cze
Łð, dziecinko!
=> 4
irb(main):008:0> baby.object_id # wskazuje ten sam obiekt
Cze
Łð, dziecinko!
=> 4
Bloki
Blok w jözyku Ruby jest czymĈ wiöcej niĔ fragmentem kodu (grupñ instrukcji). W okreĈlonym
kontekĈcie blok ma specjalne znaczenie. Jak zobaczymy, tego typu blok jest zawsze wywoäy-
wany w poäñczeniu z metodñ. W istocie okreĈlany jest terminem funkcja nienazwana.
W Ruby blok jest czösto (lecz nie zawsze) sposobem na pobranie wszystkich wartoĈci ze struk-
tury danych przez iteracjö na tej strukturze. Oznacza mniej wiöcej „daj mi wszystko, co tu masz,
po jednym na raz”. PokaĔö tu typowe zastosowanie bloku.
Przypomnijmy sobie tablicö
pacific
:
pacific = ["Waszyngton", "Oregon", "Kalifornia"]
MoĔemy wywoäaè blok na tej tablicy, aby pobraè po jednym wszystkie elementy, posäugujñc siö
metodñ
each
. Oto jeden z moĔliwych sposobów:
pacific.each do |element|
puts element
end
Bloki
_
49
Nazwa pomiödzy znakami
|
(
|element|
) moĔe byè dowolna. Blok wykorzystuje jñ jako zmiennñ
globalnñ do Ĉledzenia elementów tablicy, a póĒniej do zrobienia czegoĈ z kaĔdym elementem
po kolei. W naszym przykäadzie w bloku instrukcja
puts
wyĈwietla kolejno wszystkie elementy
tablicy:
Waszyngton
Oregon
Kalifornia
Instrukcje
do..end
moĔna zastñpiè parñ nawiasów klamrowych, co teĔ powszechnie jest stoso-
wane, by otrzymaè bardziej zwiözäy kod (tak przy okazji, nawiasy klamrowe majñ wyĔszy prio-
rytet niĔ
do..end
):
pacific.each { |e| puts e }
Metoda
each
jest dostöpna w dziesiñtkach klas, miödzy innymi w
Array
,
Hash
i
String
. Ale
proszö nie sugerowaè siö tym zanadto. Iteracja przez struktury danych nie jest jedynñ metodñ
wykorzystania bloków. Pozwolö sobie przytoczyè prosty przykäad wykorzystujñcy säowo klu-
czowe Ruby
yield
.
Instrukcja yield
Na poczñtek zdefiniujmy króciutkñ metodö
gimme
zawierajñcñ jedynie instrukcjö
yield
:
def gimme
yield
end
Aby sprawdziè, co robi ta metoda, wywoäamy jñ bez niczego i zobaczymy efekt:
gimme
LocalJumpError: no block given
from (irb):11:in `gimme'
from (irb):13
from :0
OtrzymaliĈmy komunikat o bäödzie, poniewaĔ zadaniem instrukcji
yield
jest wykonanie
bloku kodu skojarzonego z metodñ. Tego nam brakowaäo w wywoäaniu
gimme
. MoĔemy unik-
nñè takiego bäödu, posäugujñc siö metodñ
block_given?
z moduäu
Kernel
. Zdefiniujmy
gimme
,
dodajñc instrukcjö
if
:
def gimme
if block_given?
yield
else
puts "Nie mam bloku!"
end
end
if
jest instrukcjñ warunkowñ. JeĈli z wywoäaniem metody zostaä podany blok, metoda
block_given?
zwróci
true
i
yield
wykona blok; w przeciwnym razie zostanie wykonany kod
po
else
.
Wypróbujmy metodö jeszcze raz, z blokiem i bez.
gimme { print "Dzie
Ĭ dobry wszystkim."} # => Dzie
Ĕ dobry wszystkim.
gimme # => Nie mam bloku!
50
_
Rozdzia
ĥ 2. Krótka wycieczka po jýzyku Ruby
Gdy podajemy
gimme
blok, metoda wykonuje zawarty w nim kod, wyĈwietlajñc tekst Dzieþ
dobry wszystkim; jeĈli nie podamy bloku,
gimme
zwróci äaþcuch
Nie mam bloku!
. Z ciekawoĈci
moĔemy zmieniè definicjö
gimme
tak, Ĕe bödzie zawieraè dwie instrukcje
yield
, a nastöpnie
wywoäaè z blokiem. Wykona blok dwa razy.
def gimme
if block_given?
yield
yield
else
puts "Nie mam bloku!"
end
end
gimme { print "Dzie
Ĭ dobry."} # => Dzie
Ĕ dobry. DzieĔ dobry.
NaleĔy pamiötaè, Ĕe po wykonaniu instrukcji
yield
program wraca do nastöpnej instrukcji
bezpoĈrednio po
yield
. Aby to zilustrowaè, zdefiniujmy
gimme
jeszcze raz.
def gimme
if block_given?
yield
else
puts "Oh-oh. Brak bloku."
end
puts "Ca
Ĩa przyjemnoĿî po mojej stronie."
end
gimme { print "Dzi
ĂkujĂ."} # => Dzi
ĊkujĊ. Caáa przyjemnoĞü po mojej stronie.
Jestem pewien, Ĕe te drobne przykäady kodu zademonstrowaäy, jak wszechstronnym narzödziem
sñ bloki. Mogö sobie wyobraziè eksplozjö kreatywnoĈci w gäowie Czytelnika.
Aby w peäni poznaè moĔliwoĈci bloków, musimy powiedzieè coĈ o procedurach.
Bloki s
é domkniýciami
Kto z czytelników wie, czym jest domkniöcie? JeĈli ktoĈ wie, jestem peäen podziwu — zapewne
ta wiedza Ĉwiadczy o zdobytym dyplomie magistra informatyki. Tym, którzy nie wiedzñ, a sñ
ciekawi, juĔ wyjaĈniam. Domkniöcie jest nienazwanñ funkcjñ lub metodñ. Przypomina metodö
wewnñtrz metody, odwoäujñcñ siö do zmiennych z metodñ zewnötrznñ lub je wspóäuĔytkujñcñ.
W jözyku Ruby domkniöcie lub blok sñ zamkniöte w nawiasy klamrowe (
{}
) lub säowa klu-
czowe
do..end
i ich dziaäanie jest uzaleĔnione od odpowiedniej metody (na przykäad
each
).
Obiekty Proc
Ruby pozwala przechowywaè procedury (potocznie proc) jako obiekty, razem z ich kontekstem.
Dostöpnych jest kilka sposobów. Jeden z nich polega na wywoäaniu metody
new
z klasy
Proc
,
innym jest wywoäanie metody lambda albo proc z moduäu
Kernel
. Tak przy okazji, wywoäanie
metody lambda lub proc jest preferowane w stosunku do
Proc.new
, poniewaĔ
lambda
i
proc
przeprowadzajñ kontrolö parametrów.
Listing 2.4 ilustruje, jak utworzyè obiekt
Proc
na oba sposoby.
Bloki
_
51
Listing 2.4. proc.rb
#!/usr/bin/env/ruby
count = Proc.new { [1,2,3,4,5].each do |i| print i end; puts }
your_proc = lambda { puts "Lurch: 'Pani wzywa
Īa?'" }
my_proc = proc { puts "Morticia: 'Kto to by
Ī, Lurch?'" }
# Jakiego typu obiekty utworzyli
Ğmy?
puts count.class, your_proc.class, my_proc.class
# Wywo
áanie wszystkich procedur
count.call
your_proc.call
my_proc.call
Po poinformowaniu, Ĕe wszystkie utworzone obiekty sñ obiektami
Proc
, program wyĈwietla
poniĔszy tekst, wywoäujñc po kolei kaĔdñ procedurö za pomocñ metody
call
:
12345
Lurch: 'Pani wzywa
Īa?'
Morticia: 'Kto to by
Ī, Lurch?'
Metoda moĔe zostaè wywoäana z blokiem; zwróci wtedy wynik wykonania bloku, nawet jeĈli
sama metoda nie przyjmuje Ĕadnych argumentów. Przypominam, Ĕe blok musi zawsze byè
skojarzony z wywoäaniem metody.
MoĔemy teĔ „przekonaè” metodö do skonwertowania w locie skojarzonego z niñ bloku na obiekt
Proc. W tym celu musimy utworzyè argument metody poprzedzony znakiem
&
. Ilustruje to
listing 2.5.
Listing 2.5. return_block_proc.rb
#!/usr/local/bin/ruby
def return_block
yield
end
def return_proc( &proc )
yield
end
return_block { puts "Mam blok!" }
return_proc { puts "Mam blok, konwertuj
Ă na Proc!" }
WyjĈcie bödzie wyglñdaè tak:
Mam blok!
Mam blok, konwertuj
Ă na Proc!
Metoda
return_block
nie ma argumentów i zawiera jedynie instrukcjö
yield
. Zadaniem
yield
jest ponownie wykonanie bloku, gdy ten zostanie przekazany do metody. Ogromnie zwiöksza
to uniwersalnoĈè starej dobrej metody.
Nastöpna metoda,
return_proc
, przyjmuje jeden argument —
&proc
. Gdy nazwa argumentu
metody jest poprzedzona
&
, metoda przyjmie blok (jeĈli zostaä przekazany) i skonwertuje na
obiekt Proc. Metoda zawiera w treĈci instrukcjö
yield
, wiöc wykonuje blok bödñcy zarazem
procedurñ, bez potrzeby uĔycia metody
call
obiektu
Proc
.
52
_
Rozdzia
ĥ 2. Krótka wycieczka po jýzyku Ruby
Symbole
Jözyk Ruby zawiera specjalny obiekt nazwany symbolem. Na razie wystarczy nam wiedzieè
o symbolach tyle, Ĕe sñ jakby pojemnikami na identyfikatory i äaþcuchy. Symbol moĔna rozpo-
znaè po tym, Ĕe zawsze jest poprzedzany dwukropkiem (
:
).
Symbolu nie tworzy siö bezpoĈrednio przez przypisanie do niego wartoĈci. Aby utworzyè sym-
bol, naleĔy wywoäaè metodö
_sym
lub
intern
z äaþcuchem lub przypisaè symbol do symbolu.
W celu zilustrowania tego przeksztaäèmy äaþcuch na symbol i z powrotem na äaþcuch.
name = "Matz"
name.to_sym # => ":Matz"
:Matz.id2name # => "Matz"
name == :Matz.id2name # => true
Zaczyna byè niepokojñco zagmatwane? Wiem, Ĕe symbole mogñ wyglñdaè trochö niejasno.
Sñ doĈè abstrakcyjne, poniewaĔ nie wiemy tak naprawdö, co dzieje siö „pod maskñ” interpretera
Ruby. Patrzñc z wierzchu widzimy, Ĕe zawartoĈè äaþcucha
name
zostaäa magicznie przeksztaä-
cona na etykietö symbolu. No i co?
No i to, Ĕe od chwili utworzenia symbolu tylko jedna kopia symbolu jest przechowywana pod
pojedynczym adresem pamiöci, dopóki program pozostaje uruchomiony. Z tego powodu Ruby
nie tworzy jednej kopii za drugñ, lecz zawsze odwoäuje siö do tego jednego adresu w pamiöci.
Zwiöksza to wydajnoĈè programów w Ruby, poniewaĔ zajmujñ mniej pamiöci.
Ruby on Rails uĔywa mnóstwa symboli, a w miarö poznawania jözyka Czytelnik zapewne
równieĔ zacznie korzystaè z wielu z nich. W istocie Ruby wewnötrznie wykorzystuje ogromnñ
liczbö symboli. Aby siö o tym przekonaè, wystarczy wykonaè nastöpujñcñ instrukcjö Ruby:
Symbol.all_symbols
Dostaniemy listö ponad 1000 symboli!
Programistom dobrze znajñcym jözyk C# lub Java pomoĔe taka analogia: symbole
w jözyku Ruby sñ jak äaþcuchy interned, przechowywane w puli äaþcuchów intern.
Obs
ĥuga wyjétków
Ruby, podobnie jak Java, C++ i inne jözyki programowania, udostöpnia obsäugö wyjñtków.
Wyjñtek wystöpuje, gdy program wykona coĈ nieprzewidzianego i zostanie przerwany jego
poprawny przepäyw. Ruby jest przygotowany do radzenia sobie z takimi problemami, lecz
moĔemy zajñè siö nimi na wäasny sposób, wykorzystujñc obsäugö wyjñtków.
W jözykach Java i C++ stosowane sñ bloki
try
; w Ruby uĔyjemy po prostu bloku
begin
. Odpo-
wiednikiem instrukcji
catch
z Javy i C++ sñ w Ruby instrukcje
rescue
. Tam, gdzie w Javie
uĔywany jest warunek
finally
, Ruby uĔywa warunku
ensure
.
Korzystanie z obsäugi wyjñtków zostaäo opisane w rozdziale 10.