Az Ada 2005 programozási nyelv

Objektum-orientált programozás


Röviden az objektum-orientált modell változásairól:

Az Ada 95-ben egy objektum metódusát még ugyanúgy kellett jelölni, mint egy átlagos alprogramot. Legyen a csomag:

package P is
  type T is tagged...;
  procedure Op(X: T;...);
end P;

Tegyük fel, hogy van egy Y nevű, T típusú változónk. Ada 95-ben csak ezt írhattuk:

P.Op(Y,...);

Azonban egy OO programozó joggal várhatja el a következő alakot:

Y.Op(...);

ahol az Y objektum szerepel elöl, és csak a további paraméterek szerepelnek a zárójelen belül. Az Ada 95 idegesítő tulajdonsága volt, hogy a P csomagot meg kellett említeni. Ez azonban nem logikus, sőt, kifejezetten zavaró, ugyanis nem a csomag művelete ez, hanem az adott típusé. Egy összetettebb csomag esetén nem nyilvánvaló, hogy melyik csomag tartalmazza a kérdéses műveletet. A prefix jelölésmód az Ada 2005-ben már engedélyezett. Akkor helyettesíthető a P.Op(Y,...) az Y.Op(...) utasítással, ha:

Ez azonban csak szintaktikai cukor, egy kezdő számára nyújt nagy segítséget. Sokkal fontosabb a többszörös öröklődés bevezetése, mely az Ada 95 esetén nehezen kivitelezhető volt: sablonok és mutató diszkriminánsok segítségével, mely néha nem is megoldható. Az Ada 2005 a többszörös öröklődést a Java nyelv stílusában (interfészekkel) vezeti be.

A többszörös öröklődés problémája leggyakrabban akkor jelentkezik, amikor ütközés lép fel több szülő esetén. Tegyük fel, hogy mindkét szülőnek van egy azonos nevű komponense (tipikusan egy közös őstől származva). Két példányunk van? És mi történik, ha a szülőknek van egy azonos műveletük különböző implementációkkal? Az ilyen problémák erős megkötést jelentenek a szülők lehetséges tulajdonosaira. Megoldást jelent a felületek (interface-ek,intefészek) bevezetése.

A felületekre úgy tekinthetünk, mint egy komponensekkel nem rendelkező absztrakt típusra, amely rendelkezhet műveletekkel. Egy jelölt típus null eljárását bevezetni is hasznos ötletnek bizonyult: nem szükséges a ténylegeses törzset megírni, sőt, valójában nem is tehetjük meg, azonban pont olyan, mintha a törzs egy null utasítást tartalmazna.

package P1 is
  type Int1 is Interface;
  procedure Op1(X: Int1) is abstract;
  procedure N(X: Int1) is null;
end P1;

Az interface egy új foglalt szó. Az Int1 felületből származtathatunk egy konkrét típust is:

type DT is new Int1 with record ... end record;
procedure Op1(NX: DT);

Ebben az esetben DT-nek definiálhatjuk néhány komponensét az itt látott módon (habár ez opcionális). Meg kell írnunk az Op1 eljárás törzsét (mivel a DT típust nem deklaráltuk absztrakt típusként). Azonban nem kell az N alprogramot felüldefiniálnunk, bár megtehetnénk, ugyanis már úgy viselkedik, mint amelynek egy konkrét null törzse van.

Egy újabb típus számos felületből származtatható, és esetleg egy hagyományos jelölt típusból. Más szavakkal számos típusból lehet egyszerre származtatni, azonban ezek közül csak egyetlen egy lehet normál jelölt típus (amelynek elöl kell állnia). Az elsőre mint szülőre hivatkozhatunk (mely egy jelölt típus is és felület típus is lehet), bármely másra pedig mint ősre (melyek csak felületek lehetnek).

Tehát tegyük fel, hogy Int2 egy másik felület típus és T1 egy normál jelölt típus, így a következők mind megengedettek:

type DT1 is new T1 and Int1 with null record;

type DT2 is new Int1 and Int2 with record ... end record;

type DT3 is new T1 and Int1 and Int2 with ...;

További felületek létrehozása hasonlóan lehetséges:

type Int3 is interface and Int1;
...
type Int4 is interface and Int1 and Int2 and Int3;

Ebben a szerkezetben a new kulcsszó nem használt. Az ősöktől megkapja azoknak a műveleteit. Azonos műveletek esetén a null eljárás felülbírálja az absztrakt változatot, más esetekben viszont azonosnak kell lenniük.

A felületek is lehetnek korlátozottak.

type LI is limited interface;

Egy fontos szabály, hogy a nem korlátozott felület leszármazottja csak nem korlátozott lehet, a másik irány azonban nem igaz.

Az Ada 95 nem figyel az alprogramok szignatúrájában lévő hibákra, amely következményeinek okozóját gyakran igen nehéz megtalálni. Ez az Ada tervezési céljaival ellentétes, amely a helyes programok írását jelenti, valamint a hibák megtalálását lehetőleg fordítási időben elvégezni. Tekintsük:

with Ada.Finalization; use Ada.Finalization;
package Root is
  type T is new Controlled with ... ;
  procedure Op(Obj: in out T; Data: in Integer);
  procedure Finalise(Obj: in out T);
end Root;

Ebben az esetben felül szerettük volna definiálni a Controlled-től örökölt Finalize null eljárást, azonban elgépeltük: Finalise. Ezáltal az új alprogramunk nem definiálja felül az eredeti Finalize eljárást, hanem egy új műveletet vezet be, és az eredeti null eljárás fut le. Az ilyen jellegű hibákat nagyon nehéz nyomon követni.

Az Ada 2005-ben ezeket a hibákat kivédhetjük, mivel explicit megjelölhetjük az eljárásunkat, hogy az felüldefiniál egy másikat a következőképpen:

overriding
procedure Finalize (Obj: in out T);

A Finalize elgépelése esetén a fordító megtalálja a hibát. Ezt az overriding újonnan bevezetett kulcsszó teszi lehetővé. Azonban az Ada 95-tel való kompatibilitás miatt a kulcsszó használata nem kötelező, valamint például sablonok használata miatt is csak opcionális.

A szignatúra elrontása hasonló problémákat eredményez. Tegyük fel, hogy egy új, T-ből származtatott típust szeretnénk bevezetni, az Op művelet felüldefiniálásával.

package Root.Leaf is
  type NT is new T with null record;
  procedure Op(Obj: in out NT; Data: in String);
end Root.Leaf;

Az Op azonosítót helyesen írtuk le, azonban a szignatúra eltér, ugyanis a Data paraméter típusa véletlenül String lett Integer helyett. Tehát a felüldefiniálás helyett egyszerűen egy újabb változatot hozva létre túlterheltük az eredeti Op műveletet. Természetesen erre is figyelmeztet a fordító, ha a következőt írjuk:

overriding
procedure Op(Obj: in out NT; Data: in Integer);

Másrészt ha csakugyan azt szeretnénk, hogy egy új műveletet adjunk meg, akkor ezt is a fordító tudtára adhatjuk:

not overriding
procedure Op(Obj: in out NT; Data: in Integer);

Ezen túlterhelésjelzők a karbantartás közbeni hibák ellen védenek.

A következő linkeken további információt találhat az Ada 2005 objektum-orientált modelljével kapcsolatban.

Osztályok

Objektumok

Öröklődés

Polimorfizmus, dinamikus kötés

Interfészek