Az Ada 2005 programozási nyelv

Típusok, típuskonstrukciók

Típusszerkezet

A típusszerkezet lényegében megegyezik az Ada 95 típusszerkezetével. Bővebben a következő oldalakon olvashat a témáról:

Elemi típusok

Diszkrét típusok

A diszkrét típusokhoz tartozó oldalak a kövektezők:

Valós típusok

A következő oldalak a valós típusokról szólnak:

Mutató és referencia típus(ok)

A mutatók használata veszélyes, ezért az Ada 95 szigorú szabályokat vezetett be a használatukra, amelyek azonban fárasztó programozást eredményeztek túlzott szigorúságuk miatt. A szabályok nem is mindig következetesek, amint a következő példa mutatja, ugyanis minden mutató típus (access type) névvel rendelkezik, kivéve az alprogram paraméterek és a diszkriminánsok mutató típusa.

type Animal is tagged
record Legs: Integer; ... end record;
type Acc_Animal is access Animal; -- névvel rendelkező
procedure P(Beast: access Animal; ...); -- névtelen

A szimmetria teljesen hiányzik a nevesített mutató típusok és a mutató paraméterek között. Ha névvel rendelkezik, akkor mindnek van egy null értéke (ami az alapértelmezett, ha a deklarációkor nincs megadva kezdeti érték), a mutató paraméterek esetén viszont a null érték egyáltalán nem megengedett aktuális paraméterként. Sőt, a névvel rendelkező mutató típusoknak egy megszorítása, hogy csak konstans típusokat érjen el, mint

type Rigid_Animal is access constant Animal;

ami azt jelenti, hogy nem tudjuk megváltoztatni azt az értéket, amire mutat. Azonban mutató paraméterek esetén nem mondhatjuk azt, hogy

procedure P(Beast: access constant Animal); -- Ada 95-ben nem megy

Az Ada 2005-ben a legtöbb ilyen megszorítás megszűnt, ugyanis a cél a rugalmasság és az egységesség.

Most már megadható, hogy egy mutató típus (szigorú értelemben: altípus) null értékkel rendelkezhet-e. Írhatjuk:

type Acc_Animal is not null access all Animal'Class;

Ezzel garantáljuk, hogy az Acc_Animal nem hivatkozhat egy null állatra.

type Pig is new Animal with ...;
Empress_Of_Blandings: aliases Pig := ...;

My_Animal: Acc_Animal := Empress_Of_Blandings'Access; -- muszáj értéket adni

Ha nem adunk kezdeti értéket a My_Animal változónak, akkor Constraint_Error kivétel lép fel. Azt is írhatjuk, hogy not null access constant.

A null kizárásának előnye akkor látszik, amikor a mutatott objektumra hivatkozunk:

Number_Of_Legs: Integer := My_Animal.Legs;

ekkor nem kell ellenőrizni, hogy null pointerre próbálunk-e hivatkozni. Ez a változtatás gyorsabbá teszi a kódot.

A constant és a not null szabadon kombinálható a mutató paramétereknél. Tehát ezeket mind írhatjuk Ada 2005 esetén:

procedure P(Beast: access Animal);
procedure P(Beast: access constant Animal);

procedure P(Beast: not null access Animal);
procedure P(Beast: not null access constant Animal);

Az all kulcsszó itt nem megengedett, ugyanis a mutató típusok mindig általánosak (mind deklarált, mind dinamikusan létrehozott objektumokra hivatkozhatnak). A változtatások miatt egy kicsit inkompatibilis az új és a régi verzió, ugyanis az Ada 2005-ben lehet egy paraméter null értékű, míg az Ada 95 esetén nem lehetett. Az Ada 2005 már megengedi, hogy ne csak a mutató paraméter legyen névtelen mutató típus, hanem bármelyik a következök közül:

A farmos példát kiegészítjük:

type Horse is new Animal with ...;

type Acc_Horse is access all Pig;
type Acc_Pig is accesses all Pig;

Napoleon Snowball: Acc_Pig := ...;

Boxer, Clover: Acc_Horse := ...;

Most már deklarálhatunk egy állatokból álló tömböt:

Animal_Farm : constant array (Positive range<>) of access Animal'Class := (Napoleon, Snowball, Boxer, Clover);

A tömb tagjai névtelen mutató típusúak. Azonban rekordok is tartalmazhatnak névtelen mutató típusú adattagot. Jellegzetes példa a láncolt lista, mely Ada 95 (és Ada 83) esetén így nézett ki:

type Cell;
type Cell_Prtr is access Cell;

type Cell is
  record
    Next: Cell_Ptr;
    Value: Integer;
  end record;

Ada 2005-ben viszont már nem kell deklarálni a Cell_Ptr típust, tehát nincs szükség egy nem teljes deklarációra a kör megszakításához (csak teljesen deklarált típusra vagy objektumra állítható mutató). Egyszerűen írhatjuk azt, hogy

type Cell is
  record
    Next: access Cell;
    Value: Integer;
  end record;

Itt a Cell azonosítót a saját deklarációjában lehet használni. Szintén használhatjuk a névtelen mutató típust egy egyszerű változó esetén, mint

List: access Cell := ..;

Egy példa a névtelen mutató típus függvény visszatérési típusaként történő használatára:

function Mate_Of(A: access Animal'Class) return access Animal'Class;

Névtelen mutató típusok átnevezési deklarációkban is használhatóak. A mutatókkal kapcsolatos utolsó fontos változtatás az alprogram típusokra történő hivatkozás, melyet az Ada 95 vezetett be, főleg visszahívó függvények implementálására. Számos más nyelvben azonban fontos felhasználási terület a matematikai alkalmazásoké, amelyre példa az integrálás, a kódban a függvényt paraméterként adjuk át. Az Ada 83 és az Ada 95 erre azt mondja: "használj sablont". Ez azonban eléggé esetlen megoldás, az Ada 2005-ben már van alternatíva. Ada 95-ben írhatjuk:

type Integrand is access function(X: Float) return Float;
function Integrate(Fn: Integrand; Lo, Hi: Float) return Float;

Az Integrate függvény megkeresi az átadott Fn függvény integrálját a Lo és Hi határok között. Egyszerű esetben ez könnyen működik, ahol a függvény könyvtári szinten definiált. Tehát az

kiszámítására írhatjuk:

Result := Integrate(Sqrt'Access, 0.0, 1.0);

ahol az Sqrt függvény az Ada.Numerics.Elementary_Functions csomagban definiált. Azonban ha az integrálandó függvény bonyolultabb, akkor problémákat okoz Ada 95 esetén az alprogramra hivatkozás. Tekintsük a következő példát, amely kiszámítja az xy kifejezést a 0 <= x,y <= 1 négyzet alakú tartományon.

with Integrate;
procedure Main is
  function G(X: Float) return Float is
    function F(Y: Float) return Float is
    begin
      return X*Y;
    end F;
  begin
    return Integrate(F'Access, 0.0, 1.0); -- nem megengedett Ada 95-ben
  end G;

  Result: Float;
begin
  Result := Integrate(G'Access, 0.0, 1.0); -- nem megengedett Ada 95-ben
...
end Main;

Ez nem megengedett Ada 95-ben, ugyanis a szabályok megtiltják, hogy egy lokális alprogramra hivatkozó mutatót tároljunk egy globális struktúrában. Ezért mind F'Access és G'Access illegális a fenti példában.

Habár a G globálissá tehető, ezáltal a G'Access megengedetté válik, azonban az F függvény továbbra is G-be ágyazott, hogy elérje annak X paraméterét. A megoldás az, hogy az Ada 2005 bevezette az alprogramokra hivatkozó névtelen mutató típust, így az Integrate függvény a következő lesz:

function Integrate(Fn: access function (X: Float) return Float; Lo, Hi: Float) return Float;

Ezáltal a fenti példa szabályossá válik, és élettartam problémák sem lépnek fel.

Mutatókkal kapcsolatos további dolgokat lásd a következő oldalakon:

Típuskonstrukciók

Tömb típusok

A tömb típusok sem változtak az Ada 95-höz képest. A következő oldalakon olvashat ezen típusról:

Direkt szorzat típus

Az Ada 2005 rekorddal valósítja meg a direkt szorzat típust. Az idevágó oldalak:

Unió típus

Az Ada 2005 az Ada 95-höz hasonlóan támogatja az unió típust:

Halmaz típus

Ada 2005-ben a halmaz sablon csomag formájában van megvalósítva. A következő oldalon olvashat róla:

Típuskonverziók

A típuskonverzió is hasonlóképpen működik, mint az Ada 95 esetében. A szintaxisról és szabályokról bővebben itt lehet olvasni:

Változók, konstansok

A változók és konstansok sem változtak az Ada 95 óta. Bővebben:

Kifejezések, operátorok

Az Ada 95-höz hasonló, bővebben itt lehet róluk olvasni: