Az Eiffel programozási nyelv

Változók, kifejezések, láthatóság

Szintaxis

Az Eiffel egy osztály-orientált programozási nyelv, szintaxisa leginkább az Ada és a Pascal által képviselt irányvonalba sorolható be. A nyelv nem tesz különbséget a kis- és nagybetűvel írt szavak között. Általánosan elfogadott konvenció, hogy a változókat kis betűkkel írjuk, az összetett nevek tagolására pedig az aláhúzásjelet használjuk.

Egy osztály mezőit, mind az adattagokat, mind a metódusokat, Eiffel-ben feature-nek nevezzük. (Az OOP-ről bővebben.)

Láthatóság

Az osztály-orientáltságból következően a modularizáció eszköze is az osztály, így a főbb láthatósági törvényszerűségek is az osztályokban megadott szelektív láthatósághoz kapcsolódnak (ami egyben az Eiffel egyik specialitását jelenti más programozási nyelvekhez képest). Eiffel-ben mindent az osztály fogalom segítségével fejezhetünk ki (hasonlóan például a Java-hoz), más modularizációs eszköz nincs. Nincsenek globális változók, és nem létezik minősített hivatkozás sem, mivel a nyelv nem blokkstruktúrált.

Érdemes még megemlíteni, hogy Eiffel-ben a láthatóság objektum- és nem osztályszintű (mint pl. a C++ esetében). Ez azt jelenti, hogy az azonos osztályba tartozó objektumok nem láthatják egymás ,,privát''-ként (más osztály objektumai számára nem láthatóként) definiált feature-jeit, hanem ugyanazok a szelektív láthatósági szabályok vonatkoznak rájuk, mint a többi osztály objektumaira. Tehát ha azt szeretnénk, hogy az adott osztály objektumai elérhessék egy ilyen feature tartalmát, akkor azt explicite meg kell határoznunk az osztály definiciójában.

Szimbólumok típusossága, tárolási módok

Az Eiffel egy szigorúan típusos programozási nyelv, ebből következően a típusellenőrzés sem maradhatott ki belőle. A típuskényszerítés lehetőségét viszont a tervezők kihagyták, mert az sértené a nyelv szigorúan osztály-orientált felépítését. Létezik benne azonban az úgynevezett fordított értékadási kísérlet fogalma, amely az öröklődéssel összekapcsolva esetenként helyettesítheti a típuskényszerítés fogalmát, bár a tervezők nem ajánlják a használatát.

Eiffel-ben a változók alapvetően referenciaként tárolódnak, kivéve ha ezt az expanded (kiterjesztett) minősítő kulcsszóval külön meg nem változtatjuk. Ezt a kulcsszót változók deklarálásakor, illetve osztályok definiálásakor is használhatjuk. Ebben az esetben az adott szimbólum a hozzárendelt objektumot nem referenciaként tartalmazza, hanem hagyományos módon tárolva. Mivel az objektum-orientált programozásban a referenciák nagyon fontosak, a referencia típusok használata a gyakoribb Eiffel-ben, ugyanakkor a beépített típusok (pl.: INTEGER, BOOLEAN) kiterjesztett típusok. Ha T egy referencia típus, akkor bizonyos megszorításokkal expanded T néven használható a neki megfelelő kiterjesztett típus. Ugyanakkor ez fordítva nem teljesül, azaz ha egy osztályt expanded-ként definiáltunk, akkor nem képezhető belőle automatikusan referencia típus.

Példa:

-- expanded típus i : INTEGER; -- az ARRAYED_STACK referencia osztály, ezért ez referencia s1 : ARRAYED_STACK[REAL]; -- ez most egy ARRAYED_STACK objektum lesz s2 : expanded ARRAYED_STACK[REAL];

Kezdőértékek, konstansok, értékadás, átnevezés

Eiffel-ben az objektumok dinamikusan rendelődnek hozzá a szimbólumokhoz. Lehetőség van konstruktorok megadására is. A nyelv alaptípusaihoz létezik automatikus kezdőérték hozzárendelés. Lokális változók esetén a kezdőérték hozzárendelés a rutin végrehajtása előtt történik meg, attribútumok esetén pedig az objektum létrehozásakor a konstruktor eljárás végrehajtása előtt. A kezdőértékek az egyes típusok esetén a következők:

 

Típus Érték
INTEGER 0
REAL, DOUBLE 0.0
BOOLEAN false
CHARACTER null karakter
BIT_N csupa 0 bitsorozat
Minden referencia típus Void

Konstans feature-ök megadására is van lehetőség Eiffel-ben, azonban ezek alapvetően csak a nyelv alaptípusainak (BOOLEAN, CHARACTER, INTEGER, REAL, DOUBLE) objektumai közül kerülhetnek ki. Ezek értéke már fordítási időben kiderül, amit az is kulcsszó használatával rendelhetünk hozzá a szimbolumnévhez (pl. x : INTEGER is 5). Összetett típus objektumát is használhatjuk konstansként, bár ehhez egy speciális nyelvi eszközt, a once függvényt kell alkalmaznunk, így ennek értékét csupán futási időben kaphatjuk meg.

Egy szimbólumhoz új értéket többféleképpen is rendelhetünk: a hagyományos értékadás (:=) alapvetően referencia átadást jelent (hacsak nem kiterjesztett objektumokról van szó), ezenkívül lehetőség van az objektumokban tárolt hivatkozásrendszerek különböző mélységig történő duplikálására és összehasonlítására (shallow copy, deep copy) is. Eiffel-ben nincs lehetőség többszörös értékadásra (x1,...,xn := kif1,...,kifn).

Az Eiffel lehetőséget ad egy osztály feature-jeinek átnevezésére is, az öröklődéshez kapcsolódva, a rename kulcsszóval. Ennek az ismételt öröklődésben lehet fontos szerepe, illetve akkor, ha azt szeretnénk elérni, hogy a leszármazott osztályban az adott feature új neve pontosabban igazodjon az osztály funkcionalitásához, mint a régi név.

Mivel a nyelv automatikus szemétgyűjtővel rendelkezik, a változók élettartamát az határozza meg, hogy meddig hivatkoznak rájuk más objektumok.

Kifejezések

Eiffel-ben a kifejezések használata hasonlít az imperatív programozási nyelvekben megszokotthoz. Ugyanakkor mivel a nyelv az objektum-orientált módszer tiszta alkalmazására törekszik, minden operátor egy osztályműveletet (közelebbről függvényt) jelent. Egy érték kiszámítása a műveletsorozat végrehajtását jelenti, az eredmény az utoljára végrehajtott függvény visszatérési értéke. Az "x" operátornak megfelelő művelet neve az operátor típusától függően infix "x" vagy prefix "x". Az egyoperandusú operátoroknál a célobjektum egyértelmű, a kétoperandusú operátoroknál pedig a bal oldalon álló objektum játssza ezt a szerepet. A célobjektum persze sokszor névtelen temporális objektum. Például a -a*(b+c) kifejezésnek a a.prefix "-".infix "*"(b.infix "+"(c)) műveletsorozat felel meg.

Ha egy osztályban egy műveletet a fent említett módon nevezünk el, akkor annak objektumaira definiált lesz a megfelelő operátor, így tehát lehetőség van operátor túlterhelésre, bár kétoperandusú operátorok esetén az operátor kiválasztásában csak a bal oldali operandus típusa játszik szerepet. Ezzel a módszerrel átírhatjuk az Eiffel előredefiniált operátorait, de a programozó maga is definiálhat új operátorokat. Ezek az ún szabad operátorok: minden @, #, | vagy & jellel kezdődő karakter sorozat elfogadható szabad operátorként, így pl. definiálható grafikus alakzatok egy osztályában a |-| művelet két objektum távolságára, vagy a tömb osztályban adott a @ művelet, ahol a@i az a tömb i. elemét adja vissza, stb. Ha a jellemző neve egy prefix operátor, akkor a deklaráció törzse egy argumentum nélküli függvényt ír le, ha egy infix operátor, akkor a deklaráció törzse egy pontosan egy argumentumú függvényt ír le.

A kifejezésekben lehetőség van az aritmetikai típusok (INTEGER, REAL, DOUBLE) keverésére. A kétoperandusú operátorok alkalmazásakor ha az operandusok különböző típusúak, akkor először mindkét operandus a bővebb értékhalmazú típusra konvertálódik, és az eredmény is ilyen típusú lesz. Érdemes megjegyezni, hogy a konverzióban a bal oldali operandusnak nincs kitüntetett szerepe (ellentétban például a Smalltalk-kal).

Még néhány érdekesség az Eiffel beépített operátoraival kapcsolatban:

  • A Pascal nyelvhez hasonlóan az egész és valós osztás operátora nem ugyanaz. (Az egész osztás operátora a //, a valósé pedig a /). Így elkerülhetőek az abból származó meglepetések, hogy a programozó két egész számra véletlenül egész osztást alkalmaz amikor valósat szeretett volna.

  • A aritmetikai típusokra definiált a hatványozás operátor ("^"). Ez két egész szám esetén is valós eredményt ad a túlcsordulások elkerülése céljából. (Például 100^100 már nem ábrázolható 32 biten.).

  • Logikai kifejezésekben a szokásos "or", "and" és "not" operátorok mellett alkalmazható az "xor" (kizáró vagy) és az "implies" (implikáció) operátor is. Az "and" és "or" operátorok esetén nem garantált a lusta kiértékelés. Ha erre van szükség, akkor az "and then" és "or else" operátorokat kell használni, ugyanúgy, mint Adában.

  •