A REXX programozási nyelv

Absztrakt adattípusok

A Rexx objektumait metódusok és objektumváltozók (amiket attribútumoknak neveznek) építik fel. Ha üzenetet küldünk egy osztálynak, akkor valamilyen esemény történik; ha a küldött üzenet megegyezik egy metódus nevével, akkor az a metódus hajtódik végre. Csakis az objektum metódusai férhetnek hozzá az objektum változóihoz. (Gyakorlatilag minden változó alapvetően private.) Az objektumok metódusaiban az EXPOSE kulcsszóval adhatjuk meg, hogy melyik attribútumokhoz férjen hozzá az algoritmus. Minden egyéb változó lokális változó lesz a függvényben, és a függvény visszatérését követően felszabadul.

Objektumot úgy hozunk létre, hogy üzenetet küldünk egy osztálynak. (Általában a „new” metódust hívjuk meg.) Egy objektum, ami egy osztály segítségével jött létre, annak az osztálynak egy példánya lesz. Azok a metódusok, amiket az osztályok a példányok számára hoznak létre, azok a példánymetódusok. Ezek olyan objektum metódusok, amelyek minden példányban megtalálhatók. Az osztályszintű metódusok minden objektum számára elérhetőek, de nem képezik az objektum részét.

A Rexx négy objektumtípust különböztet meg:

Objektum osztály

Az Objektum osztály gyakorlatilag egy gyárnak (factory-nek) tekinthető, amivel új objektumpéldányokat hozhatunk létre. Az Objektum osztály létrehozza az objektumpéldányokat és hozzájuk rendeli a megfelelő függvényeket. Azok a metódusok lesznek csak hozzárendelve az objektumpéldányhoz, mely a példányosítás idején az osztálydefinícióban szerepel, tehát, ha ezt követően – futási időben – kiegészítjük az osztályt új függvényekkel, akkor azok csak az azt követően példányosított objektumokban lesznek megtalálhatóak.

Példányosítás során, ha az osztály rendel az objektumhoz olyan függvényt, amely az EXPOSE kulcsszóval hivatkozik az osztály valamely változójára, akkor az adott változó objektumszintű változóként jön létre az adott objektumban.

Kevert osztály

A Rexx támogatja a többszörös öröklődést. Az így létrejött osztályok kevert osztályok (Mixin Classes). Szintén kevert osztálynak neveznek minden olyan osztályt, ami objektumpéldányokat és metódusokat rendel már meglévő osztályokhoz.

Osztályokhoz úgy rendelhetünk hozzá függvényeket, hogy az INHERIT üzenetet küldjük nekik, vagy az INHERIT opcióval hívjuk meg a ::CLASS direktívát. Ezt azonban csak kevert típusú osztályokon lehetséges elvégezni.

Minden kevert osztálynak van egy alaposztálya, ami a kevert első nem kevert típusú ősosztálya. Minden kevert osztályból csak az alap osztályának leszármazottai örökölhetnek. Ha egy kevert osztály őse az Object, akkor bármely osztályt bővíthet.

Kevert osztályokat úgy hozhatunk létre, hogy egy már létező osztálynak MIXINCLASS üzenetet küldünk, vagy a ::CLASS direktívát a MIXINCLASS üzenettel hívjuk meg.

Absztrakt osztályok

Az absztrakt osztályok olyan osztály és példánymetódusok definícióit tartalmazzák, amelyek még nem elégségesek egy példány létrehozásához. Ezeket a függvényeket az alosztályok valósítják meg teljesen.

Az absztrakt osztályok létrehozása ugyanúgy megy, mint az Objektum vagy a Kevert osztályoké. Semmilyen kulcsszóval nem lehet megkülönböztetni a definiálás közben, hogy épp absztrakt osztályt kíván-e létrehozni a programozó. A Rexx nem tiltja absztrakt osztályok példányosítását. Az absztrakt osztályokban lehetnek absztrakt metódusok. Az absztrakt metódusok egyfajta helyfoglaló szerepet töltenek be, míg azokat egy alosztály felül nem definiálja. Abban az esetben, ha példányosítunk egy absztrakt osztályt, és meghívjuk annak egy absztrakt metódusát, error szintű hiba lép fel.

Meta osztályok.

A Meta osztály egy olyan osztály, amit más osztályok létrehozásához használunk fel. A Rexx egyetlen beépített Meta osztálya a Class osztály, mellyel más osztályokat tudunk definiálni. Létrehozásához a ::CLASS direktívát a METACLASS opcióval kell meghívni, majd a felhasználásához egyszerűen ebből kell származtatni.

Osztályok használata

Ha nem definiáljuk az osztály létrehozásakor, hogy mi az ősosztálya, akkor alapértelmezetten az Object lesz az. A példa azt mutatja, hogy készítünk egy osztályt, annak egy „önazonosító” függvényt, illetve egy név belső változót, a hozzá tartozó „getter-setter” függvényekkel.

::CLASS Hallgato ::METHOD tipus return "Ez egy hallgato" ::METHOD nev expose nev return nev ::METHOD "nev=" expose nev use arg nev

A „getter-setter” függvények létrehozására már létezik a nyelvben az ::ATTRIBUTE direktíva, ami amivel egy példányváltozót tudunk létrehozni, aminek lesz egy lekérdező és egy átíró függvénye.

Az ::ATTIBRUTE mintájára hozták létre a ::CONSTANS direktívát. Ez egy olyan példányváltozót hoz létre, aminek beállít egy fordítási időben ismert konstans értéket, és nem hoz létre hozzá felülíró függvényt.

A Scope

Csak az azonos láthatósági körbe tartozó (gyakorlatilag az azonos osztályban szereplő) metódusok és változók látják egymást (az ősosztályból örökölt függvények és változók másik láthatósági körbe tartoznak.). Az alosztályok definiálhatnak változókat olyan névvel, ami az ősosztályban már megvan, mert ezek már más láthatósági körbe fognak tartozni.

Példányfüggvények létrehozása

Speciális módja a példányfüggvények létrehozásának – az eddig ismertetett módon kívül – a ::SETMETHOD és az ::ENHANCEDMETHOD direktívák használata.

A ::SETMETHOD direktíva egy már meglévő objektumot egészít ki az adott nevű függvénnyel. Ez azt is jelenti, hogy ha már volt az objektumnak ilyen nevű függvénye, akkor azt felülírja az új függvénnyel.

Az ::ENHANCEDMETHOD direktívát osztályokon kell meghívni. Ez a direktíva létrehoz egy új osztálypéldányt, kiegészítve azzal a függvénnyel, ami a paraméterében van. Láthatóság tekintetében a függvény úgy viselkedik, mintha létrehoztunk volna egy új osztálydefiníciót, mely a kiegészített osztály leszármazottja.

Metódusnevek

Az metódusokra a következő elnevezési szabály áll: Egy metódusnév bármilyen string lehet, az egyetlen megkötés az, hogyha a metódusnév olyan karaktert tartalmaz, mely nem lehet azonosító (például a korábbi példánkban az = operátort) akkor a metódusnevet idézőjelbe kell tenni.

A metódusnevek feloldása igen egyszerűen megy. Ha egy osztály valamilyen üzenettel meghívunk, akkor a preprocesszor az osztályban keres egy olyan függvényt, amire illeszkedhet az üzenet string nagybetűsített (uppercase) változata. (Mivel a nyelv case-insensitive, ezért megy az összehasonlítás ily módon.)

A metódusnevek feloldásának sorrendje

A metódusnevek feloldása a következő jól meghatározott sorrendben zajlik:

  1. Az objektum saját (::SETMETHOD-dal vagy ::ENHANCEDMETHOD-dal létrehozott) metódus neveire keres a preprocesszor.
  2. Az osztály által definiált metódusok. (Fontos, ha létrehozunk egy példányt, majd az osztályt kiegészítjük egy újabb függvénnyel, akkor a példányban nem lesz benne az utólag hozzáadott függvény.)
  3. Azon metódusokra való illesztés, melyeket az objektum megörökölt. (Itt is fontos szabály, hogy az ősosztály példányosítást követő változtatása nem módosítja a már létező objektumot.) Az ősosztályok közötti keresés a második és a harmadik pontok rekurzív ismétlésével zajlik. (Azaz először a közvetlen őst vizsgálja meg, és ha ott nem találja, csak akkor veszi annak az ősét górcső alá.)

Abban az esetben, ha a preprocesszor nem talál illeszkedő nevű függvényt, meghívja az objektum UNKNOWN metódusát. Ha nem talál ilyen nevű metódust sem, akkor a metódushívás pontjára beállítja a RAISE NOMETHOD hibajelet. Ha a futtatás közben egyetlen helyen sem kapjuk el a NOMETHOD hibajelzést, akkor a kód szintaktikus hibát jelez.

Abban az esetben, ha az objektumnak van UNKNWON metódusa, akkor azt a preprocesszor két argumentummal fogja meghívni. Az első az üzenet, amit az objektumnak küldtek (a név, amelyet nem talált a metódusnevek között), és egy tömb, ami a hívási argumentumokat tartalmazza.

A metódusnevek feloldási sorrendjének megváltoztatása

A Rexx lehetőséget biztosít arra, hogy befolyásoljuk, milyen sorrendben nézze át a preprocesszor a különböző láthatósági köröket. Ennek a módjai a következőek: