Ruby.newEredetileg (még fiatalok voltunk) amikor ezt a könyvet írtuk, volt egy nagy tervünk. Le akartuk dokumentálni az egész nyelvet tetőtől talpig kezdve az osztályoktól és objektumoktól az egészen apró részletekig. Ez először nagyon jó ötletnek tűnt. Mivel a Ruby-ban majdnem minden objektum, így célszerű először erről beszélni. Illetve mi így gondoltuk. Aztán kiderült, hogy ez kissé bonyolult módja egy nyelv leírásának. Ha még nem beszéltél stringekről, Így kiötöltünk egy másik grandiózus tervet (nem véletlenül hívnak minket pragmatikusoknak). Továbbra is fentről kívánjuk a Ruby leírását kezdeni. De mielőtt nekivágnánk, adunk egy rövid fejezetet, melyben általános nyelvi tulajdonságok találhatóak példákon keresztül ismertetve, a Ruby nyelvezetében fogalmazva. Ez egyfajta minitutoriál, mely megadja a kezdő löketet a könyv maradék részének elolvasásához. A Ruby objektum-orientált nyelvMondjuk el mégegyszer. A Ruby egy egyedülálló objektum-orientált nyelv. Bármi, amit használunk, de azok eredménye is objektum. Habár más nyelvek is ugyanezt állítják magukról, más módon értelmezik, mi is az objektum-orientáltság és egy más terminológiát az általuk használt fogalmakra. Így mielőtt túl messze jutnánk a részletekben, lássuk röviden az általunk használandó kifejezéseket és jelöléseket. Amikor objektum-orientált kódot írunk, normális esetben a valóságból keresünk modellt a programunkhoz. A modellezés folyamán tipikusan azokat a dolgokat kategorizáljuk, melyeket reprezentálni akarunk kódunkban. Egy zenegép esetében a dal egy kategorizálandó fogalom. Ruby-ban ezeket az entitásokat osztály definiálásával reprezentáljuk. Az osztály állapotok (pl. a dal neve) és metódusok (dal lejátszása) összessége. Ha az osztályok készen vannak, szeretnénk példányosítani őket. A Ruby-ban ezek az objektumokat konstruktorral hozzuk létre, amely osztályhoz rendelt speciális metódus. A standard konstrukor neve
Mindkét a példány ugyanabból az osztályból van származtatva, azonban saját karakterisztikájuk van. Először is minden objektumnak saját azonosítója van (object identifier, rövidítve object id). Másodszor, definiálhatunk példány változókat, azaz olyan változókat, melyek minden példányra nézve egyedi. Ezek tárolják az objektum állapotát. Esetünkbe Dalaink nagy valószínűséggel tartalmaznak olyan példány változót, mely a dal nevét tárolja. Oszályokban definiálhatunk példány metódusokat is. Minden metódus egy darabka funkcionalitás, program blokk, mely hívható osztályon belülről és kívülről egyaránt, függően a láthatósági szabályoktól. Ezek a metódusok azonban elérhetik az objektum példány változóit, tehát az objektum állapotát. Metódusokat objektumnak történő üzenetküldéssel tudunk meghívni. Az üzenet tartalmazza a metódus nevét és a szükséges paramétereket (A metódus hívások üzenetküldéses formája a Smalltalktól ered). Amikor az objektum megkap egy üzenetet, megkeresi az annak megfelelő metódust. Ha megtalálta, végrehajtja, ha viszont nem, akkor ... erre még visszatérünk később. A metódusok és üzenetek ilyen formája talán komplikáltnak tűnik, gyakorlati szempontból ez nagyon is természetes. Nézzünk meg néhány metódus hívást (a nyilak a kifejezés végén csak a kiértékelések végeredményét mutatják).
A pont előtt áll a fogadó objektum, utána pedig a meghívandó metódus neve. Az első példában lekérdeztük egy string hosszát, a másodikban egy a "c" betű pozícióját egy másik stringben. A harmadik páldában egy szám kiszámolja saját abszolút értékét. Végezetül megkérjük Samet, játsszon el egy nótát. Érdemes itt megjegyezni egy fontos különbséget a Ruby és más nyelvek között. Mondjuk a Javában az abszolút értéket kiszámító függvény egy különálló függvény, melynek paramétere a szám. Ezt így lehetne írni:
Ruby-ban az abszolút érték kiszámítás képessége a számokba van beépítve. Csak elküldjük az
Ugyanez igaz minden Ruby objektumra. C nyelven ezt írnánk: Néhány alapvető RubyNem sok ember szeret rakás unalmas szintaxis szabályt olvasni, amikor új nyelvet sajátít el. Akkor most csalni fogunk. Ebben a fejezetben érinteni fogunk néhány fontos dolgot, amit egyszerűen ismerni kell, ha Ruby program írásába fogunk. Később, a 18. fejezetben majd elővesszük az összes lényeges részletet. Mindjárt kezdjük is egy egyszerű Ruby programmal. Írni fogunk egy metódust, ami egy személynevet tartalmazó stringet ad vissza. Ezt aztán párszor meghívjuk.
Néhány általános észrevétel: a Ruby szintaxisa tiszta. Nincs szükség utasítások végén pontosvesszőre, legalábbis addig, amíg minden utasítás külön sorba kerül. Ruby kommentek #-kal kezdődnek és a sor végéig tartanak. A kód elrendezése teljesen rajtad múlik, a behúzásnak itt nincs jelentősége. A metódusokat Miután metódusunkat definiáltuk, meghívjuk kétszer. Mindkét esetben az eredményt a
A
Habár az élet nem mindig ilyen egyszerű, a precedencia szabályok megnehezíthetik annak eldöntését, melyik argumentum melyik metódus hívás paramétere, így mi azt javasoljuk, hogy mindig használjunk zárójelezést a legegyszerűbb esetek kivételével. Ez a példa tartalmazott néhány Ruby stringet. Több módja is van stringek létrehozásának, de talán a leggyakoribb a string literálok használata: karaktersorozatok aposztrófok ( A Ruby-nak az idézőjelekkel határolt literálokkal már több a dolga. Első lépésben megkeresi a helyettesítő kifejezéseket -
a következőt eredményezi:
A második dolog, amit a Ruby az idézőjelek közé zárt stringgel tesz, az a kifejezés interpoláció. A stringen belül található
Amikor a Ruby létrehozza ezt a string objektumot, veszi a Végezetül a metóduson is tudunk egyszerűsíteni. Ruby metódus visszatérő értéke az utoljára kiértékelt kifejezés értéke, így megspórolhatjuk a
Azt ígértük, ez a fejezet rövid lesz. Azonban van még egy témánk: Ruby elnevezések. A rövidség kedvéért használni fogunk néhány olyan terminust (pl. osztály változó), amit még nem definiáltunk. Azonban azzal, hogy most elmondjuk a szabályokat, később csak könnyebb lesz megérteni a példány változókat és más hasonló fogalmat, amikor odaérünk. Ruby a következő szabályt használja az elnevezések megkülönböztetésére: az első karakter dönti el, hogyan lesz használva az adott név. Lokális változók, metódus paraméterek és metódus nevek mind kisbetűvel vagy aláhúzással kezdődnek. A globális változók dollár ($) jellel, a példány változók kukac (@), az osztály változók pedig dupla kukac (@@) jellel kezdődnek. Ettől kezdődően a nevek tetszőleges kombinációi lehetnek betűknek, számoknak és aláhúzás jelnek, azzal a kikötéssel, hogy @ jel után szám nem állhat.
Tömbök és hash táblákA Ruby tömbök és hash táblák indexelt sorozatok, azaz elemeit kulccsal címezzük. Tömbök esetében az elem sorszáma a kulcs, hash táblák esetében viszont bármilyen objektum lehet. Ráadásul mindketten dinamikusak, azaz új elem bekerülése esetén ha szükséges, növekszik méretük. Tömb elemek hozzáférése hatékonyabb, a hash tábla viszont rugalmasabb. Minden egyes tömb és hash tábla tetszőleges típusú objektumot tartalmazhat, lehet benne egészértékű szám, string, lebegőpontos szám, de ezt hamarosan látni fogjuk. Tömböt létrehozhatunk tömb literál segítségével (elemek sorozata szögletes zárójelek közé zárva). Az így megadott tömb objektum elemeit a tömb neve után szögletes zárójelbe írt sorszám segítségével címezzük meg, ahogy ezt a következő példa is mutatja.
Üres tömböt létrehozhatunk akár tömb literállal, akár a tömb osztály konstruktorával: Array.new
Néha nagy kinlódás olyan tömböt létrehozni, mely szavai vesszőket, idézőjeleket tartalmaznak. Szerencsére erre is létezik egy segítség, a
A Ruby hash táblák hasonlóak a tömbhöz. Hash literál kapcsos zárójeleket használ, közöttük pedig kulcs-érték párok vannak felsorolva. Például ha hangszerekhez szeretnénk zenekari szekciót rendelni, azt hash táblával tudjuk megtenni:
Hash táblák ugyanúgy szögletes zárójelekkel címezhetőek, mint a tömbök.
Ahogy utolsó példánkban láthattuk, hash tábla
A tömb és hash tábla objektumoknak sok hasznos funkciójuk van még: lásd a 33. oldalon és a referenciában!(?) Vezérlési szerkezetekA Ruby rendelkezik minden szokásos vezérlési szerkezettel mint pl.
Hasonló módon
A Ruby utasítás módosítók igen hasznos kiegészítők, ha az
Ugyanez rövidebben:
Hasonló módon egy
rövidebb így írva:
Ezek a módosítók biztosan ismerősek Perl programozók számára. Reguláris kifejezésekA legtöbb beépített Ruby típus ismerős lesz minden programozónak. A nyelvek többsége rendelkezik stringgel, lebegőpontos számokkal, tömbökkel és így tovább. Habár amíg a Ruby meg nem jelent, beépített reguláris kifejezés támogatás általában csak az úgynevezett szkript nyelvekben létezett (Perl, Python, awk). Ez hiba. A reguláris kifejezések, még ha titokzatosan is néznek ki, nagyon hatékony eszközök szöveg feldolgozásra. Egész könyveket töltenek meg reguláris kifejezésekről írva, így nem fogunk minden részletre kitérni külön. Helyette megnézünk néhány példát arra, hogyan működnek a reguláris kifejezések. A reguláris kifejezés semmi más, mint egyszerűen egy karakterekből álló minta, melyet stringhez akarunk illeszteni. Reguláris kifejezést Ruby-ban tipikusan per jelek közé írt karakterekkel adunk meg (/egy_minta/). És mivel a Ruby-ban vagyunk, természetesen a reguláris kifejezések is objektumok, melyekkel hasonló módon kell bánni, mint más objektumokkal. A példa kedvéért, ha olyan mintát szeretnél, amely illeszkedik a "Perl" vagy "Python" szavakra, a következő reguláris kifejezés megteszi ezt:
Per jelek határolják körbe a mintát, mely tartalmazza a két illesztendő stringet függőleges vonallal ("|", angolul: pipe) szétválasztva. Az aritmetikai kifejezésekben is használt zárójelezést itt is használhatjuk, így átírva a kifejezést, az alábbi módon fog kinézni:
Mintán belül megadhatunk ismétlődéseket is. Illeszthetünk továbbá karakterek egy csoportjára is mintán belül. Közismert példa erre olyan karakter osztályok, mint a Ezek segítségével könnyedén összeüthetünk hasznos reguláris kifejezéseket.
Ha egyszer létrehoztunk egy reguláris kifejezés mintát, hiba lenne nem használni. A
A string illeszkedő része kicserélhető másra. Erre van a Ruby-nak egy helyettesítő eljárása.
Még sok mindent el fogunk mondanunk a reguláris kifejezésekről, ahogy végighaladunk a könyvön. Blokkok és iterátorokEz a fejezet rövid leírást foglal magában a Ruby nyelv egyik erősségéről. Mi most a kód blokkokra, mint olyan kódrészletekre tekintünk, amelyek kvázi paraméterként metódushíváshoz társíthatók. Ez egy hihetetlenül erős tulajdonsága a Ruby-nak. A blokkok hasznosíthatóak callback-ként (visszahívás), továbbadott kódrészletként vagy iterátor létrehozásához. A kód blokkok egyszerűen csak
Egy így elkészített kód blokkot máris metódushíváshoz társíthatjuk. Ez a metódus ezután meg fogja tudni hívni a társított kód blokkot egyszer vagy többször is. Kód blokkot a Megjegyzés: sokan úgy vélik, a blokk társítás is egyfajta paraméter átadás. Ugyan egy szinten működik azzal, ez mégis másik történet. Célszerűbb a blokkra, mint társrutinra gondolni, amely időnként megkapja a vezérlést, majd visszaadja.
ezt eredményezi:
Nézzük meg, ahogy a blokkon belüli kód ( A
A Ruby könyvtár számos helyen alkalmazza a kód blokkokat iterátorok létrehozásához. Az iterátor olyan speciális operátor, amely az adott adatszerkezet (pl. tömb) bejárásával egy elem rákövetkezőjét adja vissza.
A következőt eredményezi:
Most nézzük meg, hogy implementálhatjuk a fenti példában használt
Ezután végigiterálhatjuk a tömb elemeit meghívva annak
Ezt eredményezi:
Ehhez hasonlóan számos ciklikus konstrukció, amelyek C-hez hasonló nyelvekben beépítettek a Ruby-ban egyszerű metódushívások. Ezek a metódusok fogják a ciklusmagot, mint blokkot hívogatni.
Lefuttatva ezt eredményezi:
Itt az 5-ös számot megkértük, hogy futtassa le a melléírt blokkot ötször, a 3-as számot, hogy addig hívja a blokkot a rákövetkező egész számokkal, amíg azok a 3-tól elérnek a 6-ig. Végezetül az a-tól e-ig terjedő betűtartományt iteráljuk az Írás és olvasásA Ruby igen széleskörű I/O könyvtárral rendelkezik. Mi viszont példáink többségénél megmaradunk pár egyszerű metódusnál. Eddig már találkoztunk kettővel, melyek kiírnak a kimenetre. A Egy másik kiíró metódus, melyet gyakran használunk, a
Eredménye:
Ebben a példában a Számos módja van programunknak a bemenet olvasására. Talán a leghagyományosabb mód a
A
Ugyanezt még inkább Ruby-s módon megírni iterátor segítségével lehet.
A fenti kód az Előre és felfeleEnnyi az egész. Befejeztük villámgyors kirándulásunkat a Ruby néhány alapvető funkciója körül. Röviden áttekintettük az objektumokat, metódusokat, stringeket, konténereket és reguláris kifejezéseket. Megnéztünk egyszerű vezérlési szerkezeteket és néhány remek iterátort is. Remélhetőleg ez a fejezet adott elég lőszert ahhoz, hogy képesek legyünk a hátralevő fejezeteket letámadni. Ideje továbblépni, feljebb és feljebb egy magasabb szintre. Következőnek az osztályokat és az objektumokat tekintjük át. Ezek egyszerre a Ruby legmagasabb szintű konstrukciói és az egész nyelv alapvető támaszai.
|