|
|||
Forrige < |
Innhold ^
|
Neste >
|
if
-setninger, tilordning og andre detaljer, blir det vanskelig å lage eksempelklasser.
Underveis i vår "ovenfra-og-nedover" beskrivelse kom vi stadig innom detaljer vi måtte dekke slik at kodeeksemplene ble fornuftige.
Derfor klekket vi ut nok en stor plan (de kaller oss ikke pragmatiske uten grunn). Vi skulle fremdeles til å beskrive Ruby fra toppen. Men før vi startet på det, skulle vi legge til et kort kapittel som beskriver alle de vanligste egenskapene til språket, som vi benytter i eksemplene, samt introduserer det Ruby-spesifikke ordforrådet, en slags mini-introduksjon
for å få sparket igang resten av boken.
Sang
for populære låter som ``Ruby Tuesday,'' ``Enveloped in Python,'' ``String of Pearls,''
``Small talk,''og så videre. Ordet objekt brukes i betydningen klasseinstans (og vil antagelig bli brukt oftere, grunnet latskap).
I Ruby blir disse objektene laget ved å kalle en konstruktør, en spesiell metode assosiert med en klasse. Den vanlige konstruktøren kalles new
.
song1 = Song.new("Ruby Tuesday") song2 = Song.new("Enveloped in Python") # og så videre |
"gin joint".length
|
» |
9
|
"Rick".index("c")
|
» |
2
|
-1942.abs
|
» |
1942
|
sam.play(aSong)
|
» |
"duh dum, da dum de dum ..."
|
number = Math.abs(number) // Java kode |
abs
til et tallobjekt og lar det gjøre arbeidet.
nummer = nummer.abs |
strlen(navn)
, mens i Ruby blir det navn.length
. Dette er en del av hva vi mener med at Ruby er et genuint objekt-orientert språk.
def sayGoodnight(name) result = "Goodnight, " + name return result end # Sengetid... puts sayGoodnight("John-Boy") puts sayGoodnight("Mary-Ellen") |
#
tegnet og varer ut til slutten av linjen.
Hvordan du legger opp koden er i stor grad opp til deg; indentering har ingen betydning.
Metoder defineres med def
nøkkelordet, fulgt av metodens navn (i dette tilfellet ``sayGoodnight
'') og dens parametre mellom parenteser. Ruby bruker ikke krøllparenteser rundt metodekroppen. I stedet avslutter du bare metodekroppen med nøkkelordet end
. Vår metodes kropp er ganske enkel. Den første linja slår sammen en ordrett streng, ``Goodnight,'', til parameteren name
og tilordner resultatet til den lokale variabelen result.
Den neste linjen returnerer det resultatet til den som kalte metoden. Legg merke til at vi ikke trengte å deklarere variabelen result
; den ble til når vi tilordnet en verdi til den.
Etter å ha definert metoden, kaller vi den to ganger. I begge tilfeller sender vi resultatet til metoden puts
, som skriver ut resultatet fulgt av linjeskift.
Goodnight, John-Boy Goodnight, Mary-Ellen |
puts sayGoodnight("John-Boy")
'' inneholder to metodekall. Først kalles sayGoodnight
og deretter puts
. Hvorfor har det ene metodekallet argumentene sine i parenteser og ikke den andre? I dette tilfellet er det opp til smak og behag. De følgende linjene gjør alle det samme.
puts sayGoodnight "John-Boy" puts sayGoodnight("John-Boy") puts(sayGoodnight "John-Boy") puts(sayGoodnight("John-Boy")) |
\n
'', som blir byttet ut med linjeskift.
puts "And Goodnight,\nGrandma" |
And Goodnight, Grandma |
#{
uttrykk
}
byttet ut med verdien av uttrykk. Vi kunne brukt dette til å omskrive den forrige metoden vår.
def sayGoodnight(name) result = "Goodnight, #{name}" return result end |
name
og setter det inn i strengen. Uttrykkene du bruker i
#{...}
kan være så komplekse du bare vil.
En snarvei gjør at du slipper å skrive krøllparentesene når uttrykket kun er en global-, instans- eller klassevariabel. For mer informasjon om strenger og andre standard typer i Ruby, se kapittel 5, som begynner på side 47.
Til slutt kan vi forenkle denne metoden litt til. En metode i Ruby returnerer den verdien som det siste uttrykket evaluerer til, så vi trenger egentlig ikke return
i metoden vår.
def sayGoodnight(name) "Goodnight, #{name}" end |
Eksempelnavn på variabler og klasser
|
a = [ 1, 'cat', 3.14 ] # Array med tre elementer
|
||
# hent det første elementet
|
||
a[0]
|
» |
1
|
# sett det tredje elementet
|
||
a[2] = nil
|
||
# dump Array-objektet
|
||
a
|
» |
[1, "cat", nil]
|
Array.new
.
empty1 = [] empty2 = Array.new |
%w
som hjelper oss med dette.
a = %w{ ant bee cat dog elk }
|
||
a[0]
|
» |
"ant"
|
a[3]
|
» |
"dog"
|
instSection = { 'cello' => 'string', 'clarinet' => 'woodwind', 'drum' => 'percussion', 'oboe' => 'woodwind', 'trumpet' => 'brass', 'violin' => 'string' } |
instSection['oboe']
|
» |
"woodwind"
|
instSection['cello']
|
» |
"string"
|
instSection['bassoon']
|
» |
nil
|
nil
når man gir den en nøkkel den ikke inneholder. Ofte er dette praktisk, da nil
betyr false
i logiske uttrykk. Men noen ganger kan du ønske å endre denne oppførselen. For eksempel, dersom du bruker en hashtabell til å telle antall forekomster av en nøkkel, er det mer praktisk om tallet null returneres når nøkkelen ikke finnes. Dette kan enkelt gjøres ved å angi en standardverdi når man lager et nytt, tomt Hash-objekt.
histogram = Hash.new(0)
|
||
histogram['key1']
|
» |
0
|
histogram['key1'] = histogram['key1'] + 1
|
||
histogram['key1']
|
» |
1
|
if
-setninger og while
-løkker. Java, C og Perl programmerere kan bli noe overrasket over mangelen på krøllparenteser.
Ruby bruker i stedet nøkkelordet end
for å angi slutten på en sammenhengende bolk med kode.
if count > 10 puts "Try again" elsif tries == 3 puts "You lose" else puts "Enter a number" end |
while
setninger med end
.
while weight < 100 and numPallets <= 30 pallet = nextPallet() weight += pallet.weight numPallets += 1 end |
if
eller while
-setning kun er et enkelt uttrykk. Da kan man bare skrive uttrykket, fulgt av if
eller while
fulgt av det logiske uttrykket.
Her følger en enkel if
-setning.
if radiation > 3000 puts "Danger, Will Robinson" end |
puts "Danger, Will Robinson" if radiation > 3000 |
while
-løkke som
while square < 1000 square = square*square end |
square = square*square while square < 1000 |
/Perl|Python/ |
|
'').
Inne i mønstrene kan du benytte parenteser på samme måte som i aritmetiske uttrykk. Det betyr at du også kunne ha skrevet mønsteret slik
/P(erl|ython)/ |
/ab+c/
slår ut på en streng som inneholder en ``a'' fulgt av en eller flere ``b''-tegn, fulgt av en ``c''. Bytt ut pluss med stjerne og /ab*c/
lager et regulært uttrykk som slår ut på en ``a'', null eller flere ``b''-er, og en ``c''.
Du kan også sammenligne mot en gruppe av tegn i et mønster. Noen vanlige eksemler er tegn-klasser som ``\s
'', som tilsvarer mellomromstegn (mellomrom, tabulator, linjeskift og lignende), ``\d
'', som tilsvarer ethvert siffer og ``\w
'', som tilsvarer ethvert tegn som brukes i typiske (engelske) ord. Punktum ``.'' tilsvarer et vilkårlig tegn.
Vi kan kombinere alle disse og komme ut med noen nyttige regulære uttrykk.
/\d\d:\d\d:\d\d/ # et tidspunkt som f.eks. 12:34:56 /Perl.*Python/ # Perl, null eller flere andre tegn, dernest Python /Perl\s+Python/ # Perl, en eller flere mellomrom, dernest Python /Ruby (Perl|Python)/ # Ruby, et mellomrom, og enten Perl eller Python |
=~
'' kan brukes for å se om noen del av en streng passer mønsteret. Dersom mønsteret finnes i strengen, returnerer kallet til =~
indeksen i strengen hvor mønsteret starter eller nil
hvis mønsteret ikke ble funnet. Dette gjør at du kan bruke regulære uttrykk som logisk uttrykk i if
og
while
setninger. For eksempel skriver følgende kodebit ut en melding hvis en streng inneholder 'Perl' eller 'Python'.
if line =~ /Perl|Python/ puts "Scripting language mentioned: #{line}" end |
line.sub(/Perl/, 'Ruby') # bytt første 'Perl' ut med 'Ruby' line.gsub(/Python/, 'Ruby') # bytt alle 'Python' ut med 'Ruby' |
do
...end
.
{ puts "Hello" } # dette er en blokk do # club.enroll(person) # dette er også en blokk person.socialize # end # |
yield
-setning. Det følgende eksempelet viser dette i praksis. Vi definerer en metode som kaller yield
to ganger. Deretter kaller vi metoden og legger en blokk til på samme linjen, etter metodekallet (og etter eventuelle argumenter til metoden).
[
Noen liker å tenke på assosieringen av en blokk til en metode som en type parameter som blir sendt med. Dette forklarer ikke hele historien. Du vil være nærmere sannheten om du tenker på blokken og metoden som korutiner, som gir kontrollflyten frem og tilbake mellom seg.
]
def callBlock yield yield end callBlock { puts "In the block" } |
In the block In the block |
puts "In the block"
) blir kjørt to ganger, en gang for hvert kall til yield
.
Du kan gi parametre til yield
kallet: disse vil bli sendt til blokken. Inne i blokken lister du opp navnene på argumentene du vil bruke for å motta disse parametrene mellom loddrette streker. (``|'').
def callBlock yield , end callBlock { |, | ... } |
a = %w( ant bee cat dog elk ) # lag en tabell a.each { |animal| puts animal } # iterer over innholdet |
ant bee cat dog elk |
Array
-klassens each
iterator som vi brukte i det forrige eksempelet. Iterator-metoden each
går over alle elementene i tabellen og kaller yield
for hvert enkelt av dem. I pseudokode kan det se ut slik:
# inne i Array klassen... def each for each element yield(element) end end |
each
metoden og angi en blokk. Blokken vil bli kalt for hvert element etter tur.
[ 'cat', 'dog', 'horse' ].each do |animal| print animal, " -- " end |
cat -- dog -- horse -- |
5.times { print "*" } 3.upto(6) {|i| print i } ('a'..'e').each {|char| print char } |
*****3456abcde |
each
metoden.
puts
skriver ut alle argumentene den får, med linjeskift etter hver av dem. Metoden print
skriver også ut sine argumenter, men uten linjeskift. Begge kan brukes for å skrive til hvilket som helst I/O objekt, men til vanlig skriver de ut til konsollet.
En annen metode for utput som vi ofte bruker er printf
, som skriver ut argumentene i et format styrt av en formatteringsstreng (akkurat slik som printf
gjør i C eller Perl).
printf "Number: %5.2f, String: %s", 1.23, "hello" |
Number: 1.23, String: hello |
"Number: %5.2f, String: %s"
at printf
skal sette inn et flyttall (tillatt fem bokstaver totalt, med to desimaler) og en streng.
Det er mange måter å lese inn innput på. Antagelig er den mest tradisjonelle måten å bruke rutinen gets
, som gir deg den neste linjen fra standard innput.
line = gets print line |
gets
har en sideeffekt: i tillegg til å returnere linjen den nettopp hentet inn, lagrer det den også i den globale variabelen $_
. Denne variabelen er spesiell, da den brukes som default argument i en del tilfeller. Hvis du kaller print
uten noen argumenter, skriver den ut innholdet i $_
. Hvis du skriver en if
eller while
-setning med kun et regulært uttrykk som logisk betingelse, blir det sjekket opp mot $_
.
Mens noen purister ser på dette som frastøtende og barbarisk, kan disse snarveiene hjelpe deg med å skrive veldig konsise programmer. For eksempel skriver det følgende programmet alle linjene på innputstrømmen som inneholder ordet
``Ruby.''
while gets # tilordner linje til $_ if /Ruby/ # sammenligner med $_ print # skriver ut $_ end end |
ARGF.each { |line| print line if line =~ /Ruby/ } |
ARGF
, som representerer den innputstrømmen som kan leses av et program.
$Log: intro.xml,v $ Revision 1.31 2003/09/13 17:52:53 kent Gjennomgang. Revision 1.30 2003/01/19 19:32:23 kent Fikser ting som kom opp i gjennomgang. Revision 1.29 2002/08/09 08:55:05 kent Fjernet siste ORIGINAL kommentaren, men fant også et sted hvor noe var droppet i oversettelsen.
Forrige < |
Innhold ^
|
Neste >
|