VI. Még bonyolúltabb class-ok

Message class

Nehezedik kissé a helyzetem, amint az egyre összetettebb osztályok felé haladok. Ezek használata sokszor nem olyan szépen átlátható, mint a csak adatokat tartalmazóké, és nagyon gyakran egymástól is függenek. Próbáltam az osztályokat olyan sorrendben említeni, hogy ne hivatkozzak egy már ismeretlen osztályra.

A Message class (a Message üzenetet jelent) legelsô rápillantásra nem jó semmire, hiszen azt csinálja, amit a ,~" jel: elküld egy objektumnak egy üzenetet. Azonban alaposabb vizsgálattal két fontos dologra derülhet fény: az egyik az, hogy ezeket az üzeneteket késleltetve is képes elküldeni, úgy, hogy nem kell az üzenet feldolgozását a programnak megvárnia; valamint hogy sok osztály használja a Message objektumokat paraméterként. Az elôbbi lehetôvé teszi a multithread, azaz több szálon futó programok készítését egyszerû eszközökkel, és az utóbbi az, ami miatt az ezután következô osztályok elôtt említem meg.

Egy message objektum létrehozásakor megadjuk, hogy majd a késôbbiekben melyik objektumnak küldjön el és milyen üzenetet. A létrehozott objektumot innentôl kezdve használhatjuk akár paraméterként olyan helyeken, ahol ilyen módon átadhatunk egy üzenetküldést, mint paramétert; vagy pedig használhatjuk közvetlenül.

Ha kézzel akarjuk az üzenet küldését indítani, ezt a send vagy a start metódusokkal tehetjük meg. Az elôbbi megvárja a végrehajtás eredményét, míg az utóbbi nem, és onnantól a program több szálon kezd futni. Az ilyen módszerrel indított programrésszel látszólag nem tudnánk többet kommunikálni, hacsak nem jut eszünkbe három idevágó metódus: completed, result és notify.

A completed metódus igaz értéket ad vissza, amennyiben az üzenet feldolgozása már befejezôdött, így ezzel lehet kívülrôl nyomon követni, hogy hol tart a háttérben folyó munka. A result megadja az üzenet végrehajtása után visszaadott értéket, amennyiben az üzenet már végre lett hajtva (completed=.TRUE) valamint van végeredmény. Ha a végrehajtás még folyik, akkor (a send-hez hasonlóan) megvárja, míg ez befejezôdik, és úgy adja vissza az értéket. Ha nincs visszaadott érték, akkor az eredménye .NIL.

A notify pedig egy igen kényelmes módszer arra, hogy mindent készen kapjunk amint az üzenet végrehajtása befejezôdött: a notify-ban megadott üzenet-objektum végrehajtásra kerül (vagyis elküldhetünk egy tetszôleges objektumnak egy üzenetet) amint az eredeti üzenetünk feldolgozása befejezôdött.

Alarm class

Ez az osztály a nyelv ébresztôórája, ahogy az a neve is (riasztás) sugallja. Kezelése rémesen egyszerû, lévén összesen kettô darab saját metódussal rendelkezik, melybôl az egyiket ráadásul nem is használjuk túl gyakran. Kezeléséhez azonban elengedhetetlen az elôzôekben - pontosan emiatt - tárgyalt Message class ismerete.

Az Alarm tehát annyit csinál, hogy egy megadott idô elteltével, vagy egy adott idôpontban elküld egy üzenetet egy tetszôleges objektumnak a paraméterként megadott Message objektum segítségével. Mindezt az objektum létrehozásakor adhatjuk meg. Az idôpontot megadhatjuk másodpercben, ekkor az idô leteltével fog az üzenet elmenni; megadhatjuk ,óó:pp:mm" formában (,22:46:12"), illetve ,óó:pp:mm nn Hón éééé" formában (,16:43:00 21 Mar 1972"), ahol a hónapot az angol rövidítésével kell megadni. Az üzenetet az elôbbiekben ismertetett Message objektum segítségével kell megadni. Például:

vekker = .alarm~new("22:30:00", .message~new(.OUTPUT, 'lineout', 'I', 'Kakukk!!'))

Ennek hatására este fél tizenegykor végrehajtódik az .OUTPUT~lineout('Kakukk!!') sor, ami a szöveg kiírását eredményezi. Természetesen a kakukkolásnál kissé bonyolultabb feladatokra is képes az osztály, és mivel annyi Alarm objektumot hozunk létre, amennyi csak jólesik, igazán kellemesen használható idôzítô eszközhöz juthatunk ezáltal.

Supplier class

Ez az osztály lehetôvé teszi azt, hogy a kupacokat (vagyis azon osztályokat, melyek adatokat tárolnak bizonyos szervezettségben) egységes módon kezeljük, és azokból az elemeket sorban kinyerjük. A hatás kissé hasonlít a kupacok makearray metódusához, de itt nem egy tömböt kapunk eredményül, hanem egy objektumot, melybôl szépen sorban ki tudjuk mazsolázni az elemeket.

Ilyen objektumot kétféle módszerrel állíthatunk elô. Az egyik _ szerintem ritkábban használt _ az, hogy a létrehozáskor megadunk két tömböt, melyekbôl az egyik az elemeket tartalmazza, a másik pedig minden egyes elemhez a hozzá tartozó indexet. Ez nem rossz módszer például olyankor, amikor össze akarjuk fésülni a külön tömbben tárolt elemeket és indexeiket.

A másik módszer sokkal hasznosabb: használjuk a kupacok supplier metódusát! Ennek eredménye egy Supplier objektum, mely szépen sorban (pontosabban sorban, ha lehet, és összevissza, ha nem) kiköpködi magából az indexeket és a hozzájuk tartozó elemeket. Példaképp nézzük az alábbi programocskát:

/* supplier class test */
jacques = .bag~new          /* peldaul nezzunk egy zsakot :) */
do 15
  jacques~put( random(10) ) /* dobalok bele nehany veletlen elemet */
end
sallyte = jacques~supplier  /* csinalunk belole egy suppliert, ami szepen sorban szallitja az elemeket */

/* kiveszunk mindenkit es kiirjuk */
do while sallyte~available
  say sallyte~index 'nevu elembol van' jacques~items( sallyte~index ) 'db'
  sallyte~next
end

A fenti programocska fog egy Zsák objektumot (Bag) és beleszór néhány véletlenszámot, majd készít belôle egy Szállítót (Supplier). Ezután szépen sorban kiírja a Szállítóban levô elemeket. A supplier metódus, mellyel elôállítottuk a kupacból a végeredményt valójában úgy viselkedik, mintha elôbb a kupacból tömböt (Array) csináltunk volna a makearray metódussal, majd ennek eredményét megadtuk volna a Supplier new metódusának.

Monitor class

Ez az osztály - melynek a neve felügyeletet, ellenôrzést jelent - képes arra, hogy üzeneteket továbbítson más objektumok felé. Igy minden üzenet, ami a célobjektumnak szól áthalad a monitoron, és ott tetszôleges átalakításon, ellenôrzésen is keresztül mehet, amennyiben ez szükséges. Az osztály lehetôvé teszi azt is, hogy az üzenet hol az egyik, hol meg a másik az objektumhoz jusson el, miközben az üzenetet eredetileg küldô programrésznek errôl nem kell tudnia.

A Monitor class alapesetben nem sokra képes: létrehozásánál megadhatjuk, hogy mely objektumnak küldje tovább az üzeneteket. Ezt le tudjuk kérdezni a current metódussal, illetve megváltoztatni a destination-nel. Azonban az öröklés segítségével nyilván bôvíthetjük az osztály lehetôségeit, és így elôfeldolgozással, ellenôrzéssel egészíthetjük ki a Monitor továbbítási lehetôségeit.

Method class

Az objektumban futó igazi ,programok" a metódusok, ezen programocskák és a hozzájuk tartozó változók zárt csomagját neveztük el végül is objektumoknak. A metódusok az OREXX-ben maguk is objektumok, rendelkeznek a hierarchiába szépen beilleszkedô típussal, és ez a Method class. Egy Method objektum valójában egy metódus neve és a hozzá tartozó programkód.

Így magában ez igazán nem hajt túl sok hasznot, azon kívül persze hogy mint minden, maguk a metódusok is beilleszkednek a ,totális" objektum-orientáltságba. Ezt az osztályt fôleg olyankor használjuk, amikor egy objektumot vagy osztályt dinamikusan, vagyis programfutás közben akarunk változtatni. (Igen! Itt erre is van lehetôség.) A menet közbeni változtatást szolgálja az alant található Object class setmethod és unsetmethod metódusa, valamint némileg a run metódus. Az elôzô kettôvel menet közben újabb metódusokat biggyeszthetünk objektumainkhoz, illetve megszüntethetjük azokat. A run segítségével ,objektumtalan" metódusokat futtathatunk az objektumunkon belül, tehát lehetôséget adva ezen ,független" metódusoknak az objektumunk belsô állapotának megváltoztatására anélkül, hogy a metódus a késôbbiekben is az objektum része maradna.

A metódus megadása elég egyszerû: a new üzenet elsô paramétereként a metódus nevét, második paramétereként pedig magát a programkódot adhatjuk meg. A programkód lehet egy string változóban, vagy egy tömbben, soronként. Az általunk készített metódusok forráskódját visszakaphatjuk a source metódussal, míg az IBMr által beszolgáltatottak esetében egy üres tömb az eredmény.

Object class

Ahogy visszafelé haladunk az objektum-hierarchiában, elôbb-utóbb eljutunk az Object classig. Ez az osztály a hierarchia alapja, vagyis minden objektum az OREXX-ben az Object class leszármazottja. Ebbôl következôen ez az osztály tartalmazza azon metódusokat, melyek minden egyes objektumban elérhetôek, noha végrehajtásuk módja természetesen az öröklési mechanizmusok szerint felülbírálható, módosítható.

Az Object osztályból közvetlenül készült objektumokat szinte soha nem használjuk, hiszen ez szinte csak egy keret, melyet bôvíteni lehet. Az osztály olyan alapvetô metódusokkal rendelkezik, mint például egy új objektum példány (instance) létrehozása, egy létezô lemásolása, azonos egyezôség vizsgálata. Alapvetô metódusok például a defaultname és az objectname, melyek az objektum nevét adják vissza (a string metódussal egyetemben), a run és a start metódusok, melyekkel az objektumnak (akár változókból vett) üzeneteket küldhetünk normál illetve párhuzamos feldolgozással, a hasmethod metódus mellyel megtudhatjuk hogy az objektum képes-e egy adott üzenetet feldolgozni vagy sem.

Érdekes a request metódus, mely - az Object class természetébôl adódóan - szintén minden objektumban megtalálható: segítségével a rendszer vagy a programunk megkérhet egy objektumot arra, hogy az értékét alakítsa át egy másfajta objektummá, amennyiben ez lehetséges. Például ha van egy Bag típusú objektumunk, és ezt megörvendeztetjük a bagobject~request('array') üzenettel, akkor arra kértük az objektumot, hogy próbálja a tartalmát Array formában visszaadni. Ilyenkor automatikusan meghívódik az objektum megfelelô MAKE metódusa, jelen esetben a makearray, ami vagy visszaad egy megfelelô formátumú objektumot, vagy egy .NIL-t jelezve, hogy erre a trükkre nem képes. Ezt a módszert használja a rendszer olyan esetekben, amikor például mindenképp stringre van szüksége, és emiatt ,felkéri" az objektumot a request('string') üzenettel hogy ha tud, készítsen magából stringet.

Class class

Ha valaki úgy gondolta, hogy az Object class nem elég elvont, akkor itt következik az az osztály, mely ezt az ûrt hivatott betölteni.

Mint tudjuk, az objektumok példányait (instances, vagyis maguk az objektumok) az objektum osztályokból (class) hozzuk létre. Tehát az osztályok azok a gyárak, amik objektumokat készítenek. A Class class egy metaclass, olyan osztály, ami nem objektum példányokat hanem osztályokat hoz létre; az elôzô hasonlattal élve olyan gyár, mely másik gyárakat állít elô.

Az Osztály osztály (ugye milyen jól hangzik?) tehát minden osztálynak ôse, így metódusait az osztályok öröklik. Logikusan ezen metódusok az objektumok létrehozását segítik, ezért ezek neve class methods, vagyis az osztályok metódusai.

Számos érdekes metódust találhatunk itt, mely az új osztályok illetve új objektum-példányok létrehozását végzik. Itt található a new, mely új objektumokat hoz létre, és amit lehetôségünk van a leszármazott osztályokban felülbírálni. A subclass és a mixinclass metódusok leszármazott osztályokat állítanak elô, az elôbbi a ,közönséges" leszármazott osztályokat készíti, míg az utóbbi típus a többszörös öröklést is lehetôvé tevô osztályok létrehozásáért felelôs.

Néha elôfordul, hogy kíváncsiskodni támad kedvünk egy osztályt illetôen, vagy hibakeresés közben érzünk csillapíthatatlan vágyat egy osztály belsejének megismerésére. Ilyenkor szolgál kellemes meglepetésként az a néhány metódus, ami vizsgálódásunkat segíti. A baseclass közli azon osztályt, mely a jelenlegi osztály alapja (ez fôleg olyankor számít, amikor többszörös örökléssel kavartuk meg a dolgot, és nem világos hogy melyik osztály az amelyikre építettünk); a metaclass megadja azt az osztályt (metaclass-t), mely a jelenlegi osztályunkat elôállította (ami esélyesen a Class class lesz); a subclasses segítségével megnézhetjük osztályunk leszármazottait, melyek függenek a jelenlegi metódusainktól, illetve ennek párjaként a superclasses ad tájékoztatást azon osztályoktól melyektôl az aktuális osztályunk függ; a methods pedig egy Supplierben megadja az osztály által ismert összes metódust (és azok programkódját, amennyiben nem a rendszer belsô kódjába tartoznak).

(Mint általában eddig minden résznél, ehhez a részhez is szerepel egy zavaros kis program a gyûjteményünkben, az ORexx Apróságok között, mely BBS-en, Interneten illetve remélhetôleg a CD-n is megtalálható. Az idevágó példa neve class.cmd, és nagyon sok class metódusra látható benne többé-kevésbé látványos példa.)

ObjectREXX támogatás

Nem mindenki tudja, hogy a Merlinben hogyan is kell váltani a ,hagyományos" REXX és az ObjectREXX között, ezért szólnék errôl pár szót.

Az alapvetô lecserélô parancs neve SWITCHRX, mely kiírja az éppen aktuális változatot és felajánlja hogy lecseréli a másikra. A lecserélés után egy rendszerindítással tehetjük érvényessé a változtatást.

Ide-oda kapcsolgatás közben feltûnt, hogy elveszett a SOM támogatásom, ami elengedhetetlen a Workplace Shell (a grafikus felületünk) valamint számos OS/2 objektum kezeléséhez. Emiatt javasolt az ObectREXX kiválasztása után lefuttatni a WPSINST nevû programot, ami regisztrálja az OREXX számára szükséges SOM osztályokat.

Gervai Péter
1997. 06. 02.
[ Elôzô lecke | Következô lecke | Tartalom ]