„Eiffel (programozási nyelv)” változatai közötti eltérés

[ellenőrzött változat][ellenőrzött változat]
Tartalom törölve Tartalom hozzáadva
Nincs szerkesztési összefoglaló
36. sor:
Az Eiffel beépített elemi típusai:
 
<source lang="eiffel">
INTEGER, REAL, DOUBLE, CHARACTER, BOOLEAN.
</source>
 
A fordító ismeri még a <source lang="eiffel">STRING</source>, az <source lang="eiffel">ARRAY</source> és a <source lang="eiffel">BIT_N</source> (bitsorozat típus) típust is. Mindezek a típusok nullaszerű értékre inicializálódnak: az <source lang="eiffel">INTEGER 0</source>-ra, a <source lang="eiffel">REAL 0.0</source>-ra, a <source lang="eiffel">DOUBLE 0.0</source>-ra, a <source lang="eiffel">CHARACTER</source> nullkarakterre és a <source lang="eiffel">BOOLEAN False</source>-ra.
 
A fordító ismeri még a STRING, az ARRAY és a BIT_N (bitsorozat típus) típust is. Mindezek a típusok nullaszerű értékre inicializálódnak: az IBNTEGER 0-ra, a REAL 0.0-ra, a DOUBLE 0.0-ra, a CHARACTER nullkarakterre és a BOOLEAN False-ra.
===Konvenciók===
Maga a nyelv nagybetűérzéketlennagybetű érzéketlen: a kis- és a nagybetűk használatát konvenciók szabályozzák. A nevekben csak ASCII karakterek szerepelhetnek; a neveket betűvel kell kezdeni, de a továbbiak lehetnek betűk, számok és aláhúzásjelek is. Az aláhúzásjel a több szavas nevek tagolására szolgál.
Az osztályok neve a konvenció szerint csupa nagybetűből áll. A konstansok nagybetűvel, a többi <codesource lang="eiffel">feature</codesource> kisbetűvel kezdődik. Az előre definiált entitások és kifejezések szintén nagybetűsek. A nagybetűérzéketlenségnagybetű érzéketlenség ellenére lehetséges egy osztály példányának az osztály kisbetűs nevét adni.
 
A <codesource lang="eiffel">;</codesource> tagolásra szolgál. A sorok végén kitehető, de nem hiba, ha nincs.
 
Konstans megadása például:
<source lang="eiffel">Solar_system_planet_count: INTEGER = 9</soure>
 
<code>Solar_system_planet_count: INTEGER = 9</code>
===Vezérlési szerkezetek===
A feltételes utasítás így néz ki:
63 ⟶ 66 sor:
</source>
 
ahol akárhány <codesource lang="eiffel">elseif</codesource> utasítás lehet, és ha nincs <codesource lang="eiffel">elseif</codesource>, akkor <codesource lang="eiffel">else</codesource> sem kötelező.
 
Többszörös elágazás írható ezzel is:
93 ⟶ 96 sor:
</source>
 
ahol is az <codesource lang="eiffel">invariant</codesource> és a <codesource lang="eiffel">variant</codesource> nem kötelező.
 
===Rutinok===
A rutinok a <codesource lang="eiffel">Result</codesource> változóban levő értékkel térnek vissza.
 
A paraméter nélküli rutinok zárójel nélkül hívhatók. Ez lehetővé teszi, hogy egy absztrakt osztály egyik konkrét utóda kiszámítsa azt, ami egy másik leszármazottban attributumattribútum.
 
A <codesource lang="eiffel">once</codesource> rutinok csak első meghívódásukkor futnak le, a későbbiekben ennek a futási eredménye érhető el ugyanazzal a névvel. Általában paraméter nélküli, de lehetnek paraméterei is. Ezekben a rutinokban a <codesource lang="eiffel">do</codesource> helyett <codesource lang="eiffel">once</codesource> szerepel.
 
Az elavult rutinok a <codesource lang="eiffel">obsolete</codesource> utasítással jelölhetők meg. Ennek egy string a paramétere, amiben leírható, hogy mit használjunk helyette.
 
A felülírás letiltható a <source lang="eiffel">frozen</source> deklarációval.
 
A felülírás letiltható a <code>frozen</code> deklarációval.
===Ágensek===
A rutinok ágensbe burkolva átadhatók paraméterként. Ezek az ágensek azonban nem azonosak a robotok programozásában használt [[ágens]]ekkel.
 
Legyen az r rutin definálvadefiniálva a C osztályban!. Ekkor a C.r rutinból ágens készíthető:
 
<source lang="eiffel">
122 ⟶ 126 sor:
</source>
 
Az <codesource lang="eiffel">'''agent''' r</codesource> kifejezés szerepelhet azokban az osztályokban is, amelyekből az r rutin egyébként is hívható lenne. Ha az r rutinnak vannak paraméterei, akkor többféleképpen is átadható, mint ágens:
 
<codesource lang="eiffel">'''agent''' r(a,?)</codesource>
 
azt jelenti, hogy az első paraméter az a, a második paraméter nyitott. Hasonlóan,
 
<codesource lang="eiffel">'''agent''' r(?,b)</codesource>
 
jelentése az, hogy az első paraméter nyitott, a második paraméter a b. De lehet ilyen is:
 
<codesource lang="eiffel">'''agent''' r(a,b)</codesource>
 
itt minden paraméter meg van adva, de a behelyettesítés még nem történt meg, hanem arra vár, hogy meghívják az ágenst.
138 ⟶ 142 sor:
Lehet akár ilyen is:
 
<codesource lang="eiffel">'''agent''' r(?,?)</codesource>
 
ami ugyanazt jelenti, mint
 
<codesource lang="eiffel">'''agent''' r</codesource>.
 
===Osztályok===
Osztályok a <codesource lang="eiffel">class</codesource> kulcsszóval deklarálhatók. Az Eiffel programok osztályokból állnak. A beépített típusok és a programkönyvtárak is osztályok. A többszörös öröklődés és az ismételt öröklődés megengedett. A metódusokat és az osztály- és példányváltozókat, konstans tagokat a nyelv közös néven <codesource lang="eiffel">feature</codesource>-nek nevezi. Alapelveiben szerepel az egységes kinézet elve, ami szerint a paraméter nélküli tagfüggvények zárójel nélkül hívhatók. Ez lehetőséget biztosít arra, hogy egy absztrakt osztály két leszármazottja közül az egyikben kiszámoljuk azt, amit a másikban megadunk.
 
Az osztályokban kiemelt szerep jut a létrehozó feature-öknek. Ezek a konstruktoroknak felelnek meg. A létrehozó feature-öket az osztály elején a <codesource lang="eiffel">create</codesource> mondatban kell felsorolni:
 
<source lang="eiffel">
162 ⟶ 166 sor:
</source>
 
A létrehozó rutinok szokásos neve <codesource lang="eiffel">make</codesource>. Ezt nem egyszerű átállítani, ezért javasolt, hogy az egyik létrehozó rutin a <codesource lang="eiffel">make</codesource> legyen. Ezek a rutinok indíthatók el példányosításkor:
 
<source lang="eiffel">create x.make(a : INTEGER, b : STRING, c : ACCOUNT)</source>
Osztályon belül nincs túlterhelés, de különböző osztályokban szabad egy műveletet ugyanazon a néven deklarálni.
 
Absztrakt osztályok és rutinok a <codesource lang="eiffel">deferred</codesource> kulcsszóval deklarálhatók. Egy absztrakt osztály utódai mindaddig absztraktak maradnak, ameddig az absztrakt rutinokat nem implementálják. Konkrét osztályok utódai is absztrakttá tehetők ugyanezzel a kulcsszóval. Az absztrakt osztályok közvetlenül nem példányosíthatók, csak konkrét utódaik révén.
 
Az osztályok alapesetben referenciák révén példányosulnak. Ha ezt nem akarjuk, akkor az osztályt <codesource lang="eiffel">expanded</codesource>-nek kell deklarálnunk. Nem expanded osztályok példányai is lehetnek nem referenciák, ha <codesource lang="eiffel">expanded</codesource>-ként hozzuk létre őket. Az alaptípusok is expanded osztályok.
 
<source lang="eiffel">
185 ⟶ 189 sor:
Az üres referencia a Void, ami a NONE fiktív osztály egyetlen példánya. Ha egy osztály <code>attached</code>, akkor az ilyen osztályú objektumok nem lehetnek Voidok. Az <code>expanded</code> osztályok implicit <code>attached</code> tulajdonságúak is, mivel nem referenciák. Az <code>attached</code> ellentéte a <code>detachable</code>. Újabban az <code>attached</code> az alapértelmezett, de a régebbi verziókban a <code>detached</code> volt az alapértelmezés. Kompatibilis módban megint a régebbi verzió az érvényes. Erre külön figyelni kell. Az <code>attached</code> típusú tagok nem vehetnek fel <code>detached</code> típusú értéket. Ez alól kivétel, ha egy elágazásban ellenőrizzük, hogy nem Void-e.
 
Az alacsony szintű pointereketmutatókat a <source lang="eiffel">POINTER</source> osztály példányai pótolják.
 
Az osztályokban <codesource lang="eiffel">Current</codesource> jelöli az adott példányt. Az adott példány dinamikus típusára a <codesource lang="eiffel">like Current</codesource> utal. Ez lehetővé teszi, hogy a rutinok értelmezési tartománya szűküljön az öröklődés folyamán, ami veszélybe sodorja a típusbiztonságot, hiszen az értelmezési tartomány nem szűkíthető típusbiztonságos módon. Ezen a catcall segíthet.
 
===Öröklődés===
227 ⟶ 231 sor:
A szerződések alakja abban az osztályban, ahol az öröklésben először definiálják az illető feature-t:
 
<source lang="eiffel">
<code>
feature nev
<span style="color:blue">
require
 
'''feature''' ''nev''
 
''require''
 
--az elofeltetelt leiro allitasok
do
 
begin
'''do'''
 
''begin''
 
--a rutin utasitasai
ensure
 
''ensure''
 
--az utofeltetelt leiro allitasok
end
 
invariant
'''end'''
 
''invariant''
 
--az invarianst leiro allitasok
</spansource>
</code>
 
Az öröklődés folyamán az előfeltételek enyhülhetnek, az utófeltételek szigorodhatnak. Ha nem írunk elő- vagy utófeltételt, akkor azok azonosan igazak lesznek. Ha egy rutinnak nincs előfeltétele, akkor a továbbiakban sem lehet, viszont az utófeltételben már lehetnek vállalásai. Az előfeltételhet vaggyal, az utófeltételhez éssel lehet továbbiakat hozzávenni:
 
<source lang="eiffel">
<code>
feature nev
<span style="color:blue">
require else
 
'''feature''' ''nev''
 
''require else''
 
--az elofeltetelt leiro allitasok
do
 
begin
'''do'''
 
''begin''
 
--a rutin utasitasai
ensure then
 
''ensure then''
 
--az utofeltetelt leiro allitasok
end
 
</source>
'''end'''
 
</span>
</code>
 
Többszörös öröklődés esetén is az előfeltételek összevagyolódnak, az utófeltételek és az invariánsok összeéselődnek.
284 ⟶ 263 sor:
Az Eiffel lehetővé teszi, hogy egy rutint, aminek nem volt paramétere, újraimplementáljunk attributumként. Ekkor az előfeltételek elfelejtődnek, az utófeltételek és az invariánsok az osztály invariánsai lesznek.
 
Az <codesource lang="eiffel">only</codesource> a megváltoztatható elemeket jelölheti ki. Az utófeltételben az <codesource lang="eiffel">old</codesource> a rutin futásának kezdetekor meglevő értékekre hivatkozik. A <codesource lang="eiffel">check</codesource> egyes ellenőrzendő állításokat jelöl meg. Ha a fordítónak a megfelelő opciót adjuk, akkor az ellenőrzi ezeket az állításokat.
 
===Kivételkezelés===
Az Eiffel nyelv a normál tevékenységtől való eltérést első vonalban a szerződésekkel fogja meg. A kivételek megmaradnak kivételes eseménynek. Akkor kerül rájuk sor, ha az adott rutin nem tudja biztosítani az utófeltételét. Ekkor az az elvárás, hogy legalább az osztályinvariánst állítsa helyre. A kivételkezelésre a rutin törzsén kívül, az <codesource lang="eiffel">end</codesource> előtt elhelyezett <codesource lang="eiffel">rescue</codesource> mondat szolgál. Innen a <codesource lang="eiffel">retry</codesource> a rutin elejére visz vissza, hogy egy másik módon próbálja meg biztosítani az utófeltételét. Ha nincs kiírva, akkor az osztály alapértelmezett rescue rutinja, az esetleg átnevezett <code>default_rescue</code> hívódik meg. Gyakran a konstruktort teszik meg default_rescue-nak, hiszen annak is az a dolga, hogy beállítsa az osztályinvariánst. Ha nem sikerült előállítani az utófeltételt, akkor a kivétel továbbdobódik a hívóba.
 
Egy Eiffel rutin vázlata a <codesource lang="eiffel">rescue</codesource> mondattal:
 
<code>
<span style="color:blue">
 
'''feature''' ''nev''
 
'''do'''
 
''begin''
 
<source lang="eiffel">
feature nev
do
begin
--a rutin utasitasai
rescue
 
''rescue''
 
--a kivételek kezelése
retry
end
</source>
 
Kivételek az EXCEPTIONS osztályból származtathatók.
''retry''
 
'''end'''
 
</span>
</code>
 
Kivételek az EXCEPTIONS osztályból származtathatók.
===Generikusok===
Az általánosítás és az absztrakció az Eiffel nyelv alapelvei közé tartozik. A módszertan kiemelten kezeli az általános, de specializálható szerkezeteket. Bertrand minden projekthez javasol egy általánosítási szakaszt, ahol a projektben megalkotott osztályokat lehetőség szerint általánosítják. Generikusok valósítják meg például az adatszerkezeteket.
318 ⟶ 288 sor:
Egy generikus osztály vázlata:
 
<source lang="eiffel">
<code>
class SHD[G]
<span style="color:blue">
feature
'''class''' ''SHD''[''G'']
 
'''feature'''
 
--definiciok
end
 
</source>
'''end'''
</span>
</code>
 
Egy általános generikusban csak olyan műveletekre szabad hivatkozni, amelyek általánosságban minden osztályra meghívhatók, különben a generikus hibás lesz, és nem fog lefordulni. Megkötésekkel ez a hiba javítható:
 
<source lang="eiffel">
<code>
class SORTABLE_ARRAY[G->COMPARABLE]
<span style="color:blue">
feature
'''class''' ''SORTABLE_ARRAY''[''G''->''COMPARABLE'']
 
'''feature'''
 
--definiciok; hasznalhatja az osszehasonlitast, a COMPARABLE muveleteit
end
 
</source>
'''end'''
</span>
</code>
 
Keverhető a nem korlátozottal:
 
<source lang="eiffel">
<code>
class HASH_TABLE[G, H-> HASHABLE]
<span style="color:blue">
feature
'''class''' ''HASH_TABLE''[''G'', ''H''-> ''HASHABLE'']
 
'''feature'''
 
--definiciok
end
</source>
 
'''end'''
</span>
</code>
===Tömbök===
Tömbök megadhatók az ARRAY generikus osztály példányaiként, vagy például így:
 
<source lang="eiffel">
<code>
<span style="color:blue">
tomb = <<4, 6, 9>>
</spansource>
</code>
 
Ez egy manifeszt tömb, típusa <source lang="eiffel">ARRAY[INTEGER]</source>, tehát ekkor is a generikus <source lang="eiffel">ARRAY</source> osztály áll a háttérben.
 
Manifeszt konstansok stringekhez is elérhetők:
 
<source lang="eiffel">
INTEGER = "Go get a life!"
</source>
 
Használható az <codesource lang="eiffel">unique</codesource> is: <code>
<spansource stylelang="color:blueeiffel">
a, b, c, n = unique
</spansource>
</code>
 
A fordító ad nekik értéket. Ez pótolja a felsorolási típust.
 
===Tuple és rutin típusok===
A TUPLE az Eiffel direkt szorzat típusa. Hasonlít a generikusokra, de nem az, hiszen akárhány paramétere lehet:
 
<source lang="eiffel">
<code>
<span style="color:blue">
TUPLE[] = TUPLE :> TUPLE[STRING]
 
TUPLE[STRING] :> TUPLE[STRING, INTEGER]
 
TUPLE[STRING, INTEGER] :> TUPLE[STRING, INTEGER, STRING]
 
--...
</spansource>
</code>
 
ahol is a hosszabb TUPLE a kezdőszeletét tartalmazó <source lang="eiffel">TUPLE</source> altípusa <source lang="eiffel">(:>)
</source>. Emellett még teljesül az is, hogy a bővebb típust tartalmazó TUPLE tartalmazó típus <source lang="eiffel">(<:):
</source>:
 
<source lang="eiffel">
<code>
<span style="color:blue">
TUPLE[] = TUPLE
 
TUPLE[STRING] <: TUPLE[ANY]
 
TUPLE[STRING, INTEGER] <: TUPLE[ANY, ANY]
 
TUPLE[STRING, INTEGER, STRING] <: TUPLE[ANY, ANY, ANY]
 
--...
</spansource>
</code>
 
A rutin típusok leszármazása:
 
A rutinok típusa a <source lang="eiffel">ROUTINE
</source>; ebből származik a <source lang="eiffel">PROCEDURE</source> és a <source lang="eiffel">FUNCTION</source> típus. A logikai függvények típusa a PREDICATE a FUNCTION altípusa. A TUPLE-hoz hasonlóan további altípusok képezhetők:
 
<source lang="eiffel">
<code>
<span style="color:blue">
ROUTINE[TUPLE[]] = ROUTINE[TUPLE] = ROUTINE :> ROUTINE[TUPLE[STRING]]
 
ROUTINE[TUPLE[STRING]] :> ROUTINE[TUPLE[STRING, INTEGER]]
 
ROUTINE[TUPLE[STRING, INTEGER]] :> ROUTINE[TUPLE[STRING, INTEGER, STRING]]
 
--...
</spansource>
</code>
 
valamint
 
<source lang="eiffel">
<code>
<span style="color:blue">
ROUTINE[TUPLE[]] = ROUTINE[TUPLE] = ROUTINE
 
ROUTINE[TUPLE[STRING]] <: ROUTINE[TUPLE[ANY]]
 
ROUTINE[TUPLE[STRING, INTEGER]] <: ROUTINE[TUPLE[ANY, ANY]]
 
ROUTINE[TUPLE[STRING, INTEGER]] <: ROUTINE[TUPLE[ANY, ANY, ANY]]
 
--...
</spansource>
</code>
 
ahol a TUPLE-k a paramétereket tartalmazzák. A függvények általános típusa hasonló, csak kibővül a visszatérési értékkel:
 
<codesource lang="eiffel">FUNCTION[TUPLE, T]</codesource>
 
ahol T a visszatérési érték típusa. Az altípusok a ROUTINE altípusaihoz hasonlóan képződnek, a visszatérési érték figyelembe vételével.
451 ⟶ 388 sor:
 
===Példaprogram===
<source lang="eiffel">
<code>'''class'''
class
''HELLO_WORLD''
'''create'''HELLO_WORLD
create
''make''
'''feature'''make
''make''feature
'''do'''make
do
''io.put_string'' ("Hello, world!")
''io.put_new_line''
'''end'''
'''end'''</code>
</source>
 
==Jegyzetek ==