A Pascal nyelvben számos előre definiált adattípus létezik. Ezek három csoportba sorolhatók: sorszámozott (ordinal), valós (real) és szöveg (string). A nyelv kibővítése során szükséges volt újabb típusok bevezetése (pl.: LongBool, DateTime, Variant, ...), többek között a Windows operációs rendszerrel való kompatibilitás miatt. Ebben a pontban ezeket vesszük sorra. (Azok kedvéért, akik nem ismerik nagyon a Turbo Pascalt, nem csak az új típusok vannak felsorolva.)
Felhasználói típust, -szinonímát a type kulcsszó után vezethetünk be név = típusdefiníció; alakban.
Az ilyen típusok azzal a fontos tulajdonsággal bírnak, hogy értelmezett rajtuk egy rákövetkezési reláció, ami a <, >, =, <= ,>= operátorokkal kérdezhető le, valamint mindannyiukon használható néhány beépített eljárás. Ezek az eljárások a következők:
A sorszámozott típusokon használható beépített eljárások |
|
Eljárás |
Hatása |
Dec |
A paraméterként megadott változó értékét eggyel, vagy a második paraméter megadása esetén annak értékével csökkenti. |
Inc |
A paraméterként megadott változó értékét eggyel, vagy a második paraméter megadása esetén annak értékével növeli. |
Odd |
True (igaz) értéket ad vissza, ha argumentuma páratlan szám. |
Pred |
A sorszámozott típusú érték megelőzőjét adja vissza. |
Ord |
A sorszámozott típusú érték sorszámával tér vissza. |
Succ |
A sorszámozott típusú érték rákövetkezőjét adja vissza. |
Low |
A sorszámozott típusban tárolható legkisebb értékkel tér vissza. |
High |
A sorszámozott típusban tárolható legnagyobb értékkel tér vissza. |
A legfontosabb sorszámozott típusok a következők: egész szám (Integer), logikai típus (Boolean) és a karakter (Char). Az egyes csoportokba több, hasonló jellemzőkkel bíró adattípus tartozik, melyek reprezentációjukban illetve értékkészletükben térnek el egymástól. Ezeken kívül a felhasználónak is van lehetősége új sorszámozott típus megadására.
A következő táblázat az egész számok tárolására alkalmas sorszámozott adattípusokat tartalmazza:
Egész típusok |
||
ShortInt |
Előjeles |
8 bit |
SmallInt |
Előjeles |
16 bit |
LongInt |
Előjeles |
32 bit |
Int64
|
Előjeles | 64 bit(Delphi 4-től) |
Integer |
Előjeles |
Verziófüggő (Delphi 1 – 16 bit; Delphi 2-től – 32 bit) |
Byte |
Előjel nélküli |
8 bit |
Word |
Előjel nélküli |
16 bit |
LongWord |
Előjel nélküli |
32 bit (Delphi 4-től) |
UInt64 |
Előjel nélküli |
64 bit (Delphi 2007-től) |
Cardinal |
Előjel nélküli |
Verziófüggő (Delphi 1 – 16 bit; Delphi 2-től – 32 bit) |
Látható, hogy vannak rendszerfüggő típusok. Ennek oka, hogy ez a két leggyakrabban használt típus, és a hatékonyság érdekében ezek közvetlenül megfelelnek a CPU által használt számoknak.
A logikai típusokat is táblázatban foglaljuk össze:
Logikai típusok |
||
Boolean, ByteBool |
1 byte |
|
WordBool |
2 byte |
|
LongBool |
4 byte |
A táblázatban szereplő Boolean felel meg az eredeti
Pascal logikai típusának. Az ilyen típusú változó a True
(1) vagy False (0) értékek valamelyikét veheti fel. A másik
három típust numerikus Boolean típusnak nevezzük, és a Windows
API-val való kompatibilitás miatt kerültek a nyelvbe. Rájuk az a
jellemző, hogy minden nem 0 értéket True-nak értelmeznek, a
különbség a maximális elfogadott szám nagyságában van.
Érdekesség, hogy a Delphi 3-tól kezdődően a Visual Basickel és az
OLE Automationnel való kompatibilitás miatt a numerikus Boolean
típusok az igaz értéket a -1-gyel, a hamis értéket pedig a 0-val
jelölik. Egész érték Boolean-ra történő konvertálása 0
esetén False, minden más esetben True lesz.
Delphiben a karakterek ábrázolására két típust használhatunk: az ANSIChar és a WideChar típusokat. Az előbbi a 8 bites karakterek, míg az utóbbi a 16 bites Unicode karakterek tárolására alkalmas. A Pascalból ismert Char típus a Delphi 2009 előtt az ANSIChar-nak, attól kezdve a WideChar-nak felel meg.
A részintervallum típus felhasználó által meghatározott típus. Lényege, hogy egy nagyobb intervallumon belüli kisebb intervallumot határozunk meg. A részintervallum típusának meghatározásához nem szükséges a bővebb intervallum megadása, elég abból két konstans érték (az új típus legkisebb és legnagyobb elemének) megadása. A két értéknek természetesen valamely már ismert sorszámozott típusúnak kell lennie, és az új típus is sorszámozott típusú lesz. Példák részintervallum típusra:
Ez is gyakran használt, felhasználó által meghatározott adattípus. Magunk is készíthetünk felsorolás típust, ha a típusértékeket felsorolva adjuk meg, illetve természetesen, ha meglévő felsorolás típus altípusát készítjük el. Minden felsorolás típusból készített altípus is felsorolás típus, tehát a részintervallumai, illetve tetszőleges kiválogatott elemei is. Példa:
Az egyes értékek sorrendje egyértelműen meghatározott, az első érték indexe nulla, következő az egy és így tovább. (Ezeket az értékeket adja vissza az Ord függvény.)
A megszámlálható típusoknak többféle ábrázolása létezik Delphiben. Alapállapotban az ábrázolási mód 8 bites, feltéve, ha 256 elemnél kevesebbet tartalmaz az adott típus. Emellett létezik 16 bites és 32 bites ábrázolási mód is, amire érdemes odafigyelni, mert a C++ könyvtárak általában 32 bites ábrázolást használnak. Nagyobb ábrázolási módot a {$Z+} fordítási direktívával kérhetünk.
A valós számokat a Delphi lebegőpontosan ábrázolja, különböző méretekben.
Valós típusok |
|||
Típus |
Intervallum |
Szignifikáns számjegyek |
Méret (byte) |
Real48 |
2,9 * 10-39 .. 1,7 * 1038 |
11-12 |
6 |
Single |
1,5* 45..3.4*1038 |
7-8 |
4 |
Double |
5,0*10-324..1,7*10308 |
15-16 |
8 |
Extended |
3,4*10-4932..1,1*10493 |
19-20 |
10 |
Comp |
-2^63+1 .. 2^63-1 |
19-20 |
8 |
Currency |
-922337203685477.5808 .. 922337203685477.5807 |
19-20 |
8 |
A Single, Double és az Extended az IEEE nemzetközi lebegőpontos szabványnak megfelelő típusok. Ezek a matematikai koprocesszor által támogatottak, így alkalmazásukkal a lehető leggyorsabb kód hozható létre. A Real48 típus nem felel meg ennek a szabványnak, így használata nem ajánlott. Csak a Pascallal való kompatibilitás miatt maradt a nyelv része. A Comp gyakorlatilag az Int64-nek felel meg, viszont nem rendelkezik az egész típusukra értelmezett műveletekkel. A Currency négy tizedes jeggyel rendelkező fixpontos érték.
A Real típusnév fordítótól függően a Real48 vagy a Double típusnak felel meg, figyeljünk erre oda, ha ezt a típust használjuk.
A mutató típus olyan változót határoz meg, amely egy adott memóriaterületre mutat. Példa:
A fenti deklaráció hatására a p változó értéke NIL. Ez azt jelenti, hogy a mutató sehova sem mutat. Ezután hozzárendelhetünk egy neki megfelelő típusú változót az @ operátor segítségével, vagy a heap memóriában új változót hozhatunk létre a New eljárással. Ekkor a memória felszabadítását is nekünk kell elvégezni, ha a változóra többé nincs szükségünk. Ezt a Dispose eljárás segítségével tehetjük meg.
A Delphiben lehetőség van típus nélküli mutató létrehozására is. (Ez hasonló, mint a C nyelvben a void* .) Ekkor azonban memóriaterületet nem a New, hanem a GetMem eljárással foglalhatunk, melynek meg kell adni a foglalni kívánt memória méretét, a felszabadítás pedig a FreeMem-mel történik.
Object Pascalban kétféle mutatónk van: típusos és típus nélküli. Ezek deklarációja a következőképp történik:
Mindkét mutatótípusra értelmezett az értékadás, pl:
A típusos mutató esetén a ^ postfix operátorral érhetjük el a mutatott objektumot:
Ha az $X direktíva be van kapcsolva, akkor tömbre vagy rekordra mutató pointernél a mutatott objektum elemeinek eléréséhez nem kell a ^ jelet kiírni.
Előre-hátra léptetésre van lehetőség az Inc() és Dec()
függvények segítségével. Csak a típusos mutatókat tudjuk léptetni, annyi
bájttal, amennyi a mutatott típusnak megfelelő adatméret.
Azonos
típusú mutatók esetén használhatjuk az = és <>
összehasonlító műveleteket. A nil konstans és a pointer
típusú mutatók bármilyen típusú mutatóval összehasonlíthatók.
A
mutatók típusa típuskonverzióval megváltoztatható. Ilyen módon a pointer
típusú mutatókhoz is rendelhetünk típust.
Az Addr() függvény
és a @ operátor segítségével bármely Pascal objektum (függvény,
változó, stb.) címét lekérdezhetjük, és egy mutatónak értékül
adhatjuk.
A Ptr() és az Assigned() utasítással egész
értékeket alakíthatunk pointer típusú mutatóvá:
A könyvtári függvények nil értékű mutatóval térnek vissza hiba esetén, ezért használatukkor erre mindig figyelni kell!
Object Pascalban a pointer típussal általános mutatót (mint pl. C-ben a void*) deklarálhatunk. Mivel az így létrehozott mutató nem rendelkezik konkrét típussal, ezért a new() eljárást nem használhatjuk memóriafoglalásra. Ebben a esetben adott bájtnyi memóriát a GetMem() eljárás segítségével foglalhatunk le, és a FreeMem() eljárás segítségével szabadíthatunk fel. Ezek az eljárások a System unitban találhatóak.
Dinamikus memóriaterületet a Sysutils modulban található AllocMem függvény segítségével is foglalhatunk, ekkor a lefoglalt memóriaterület 0-kkal lesz feltöltve. A visszatérési érték a lefoglalt területre mutató pointer.
A fenti alprogramok segítségével lefoglalt memóriablokk mérete a ReallocMem eljárással megváltoztatható:
Az alkalmazás által lefoglalt memóriablokkok számát az AllocMemCount, a lefoglalt memória összméretét pedig az AllocMemSize Integer típusú globális változók tartalmazzák.
A variáns típusnak az a kellemes jellegzetessége, hogy nem kell a változó deklarálás időpontjában eldönteni, milyen legyen a típusa, hanem Variant típusúra deklaráljuk, és a változónak a program során adhatunk bármilyen értéket, számértéket, karakterest, tömböt, de még objektum is lehet. Attól függően, hogy mit adtunk neki értékül, olyan típusúvá válik (legalábbis amíg meg nem változtatjuk a tartalmát más típusra). Kompatibilis lesz a benne lévő érték típusával, bírja annak a műveleteit, értékül adható olyan váltózónak, melynek ilyen a típusa. Például a következő programsorok működnek:
A fenti sorokból is látszik, hogy a Variant igen rugalmasan használható adattípus. Azonban a fentihez hasonló kód írása rengeteg veszélyt rejt magában. Például ha a V változónak kezdetben nem számot tartalmazó Stringet adunk értékül, akkor azt a Delphi nem tudja Integerré konvertálni, és ez kivételt vált ki. Ezért ha tehetjük, inkább használjunk egyéb Delphi adattípusokat. Másik hátránya a Variant típus használatának a lassúsága. A Variant típusa és értéke mindig futás közben dől el, ezért az ilyen változókat tartalmazó kódrészletek szinte interpretált (futás közben értelmezett) kódrészleteknek is tekinthetők, és ez nagymértékben lassítja a programunk futását.
A Pascalban létezik egy alprogram típus, amely a C-beli függvénymutatóhoz hasonlóan működik. Az alprogram típusok létrehozásakor meg kell adni a paraméterek listáját és függvény esetén a visszatérési érték típusát is. Példák:
A fenti sorok definiálnak egy adott számú és típusú paraméterrel rendelkező eljárástípust, és egy ilyen típusú változót. Ezután a változóknak értékül adhatunk ilyen fejléccel rendelkező eljárást. A változóhoz a NIL értéket is rendelhetjük. Ez nagyon hasznos, akkor, ha egy definiált eseményt bizonyos esetben le akarunk tiltani, vagy hol ezt, hol azt akarunk végrehajtani valamilyen eseményére.
Ez a típus hasonló az alprogram típushoz, de az alprogram címén kívül tartalmazza annak az objektumnak a címét is, amelyre a metódust meg kell hívni. Deklarációjakor az alprogram típus deklarációját ki kell egészítenünk az of object kulcsszavakkal.
Ha a TMainForm osztály rendelkezik egy ButtonClick nevű metódussal, amelynek egy TObject típusú paramétere van, akkor az alábbi értékadás érvényes:
Az osztályreferencia típus arra való, hogy megmondjuk a létrehozott osztály nevét és ősét, de nem deklaráljuk még a többi részt, mert azt később is ráérünk, vagy egyszerűen még nem akarjuk, illetve még nincs pontosan meg. (pl.: csoportmunka és azt a típust más írja, de mi fel szeretnénk már használni). Illetve ez arra is jó, ha fordítási időben nem tudjuk még milyen típusú lesz a deklarálni kívánt változó, megadjuk az ős referenciatípusát, és tetszőleges altípusát hozhatjuk majd a programban létre.
A Windows operációs rendszerrel való kompatibilitás érdekében szükséges volt egészen új adattípusok bevezetésére is (Pl.: DWORD, UINT). Ezek közül a legfontosabb az úgynevezett handle (kezelő). A típus neve THandle, és a következőképpen van definiálva:
A handle adattípusokat tehát úgy használjuk, mintha számok lennének, de nem szabad elfelejtenünk, hogy valójában nem azok. Ezek a Windows által a belső adatszerkezetekhez hozzárendelt azonosítók. A Windows alatt minden ablaknak, ikonnak, erőforrásnak saját, egyedi azonosítója van, melyet a rendszer a létrehozásakor automatikusan hozzárendel. A későbbiekben ezzel a számmal (handle-lel) hivatkozhatunk rá. (Pl.: ablak mozgatása, láthatóvá tétele, stb.) Az Integer típushoz hasonlóan a THandle típus nagysága is más a 16 illetve 32 bites Windowsban, ezért a Delphiben is.
Több dimenziós tömb megadásának többféle szintaktikája is van, de ezek szemantikailag nem különböznek. array [felsorolás_típus_1, felsorolás_típus_2,... felsorolás_típus_n] of típusnév ugyanaz a tömb, mint ha azt mondanánk: array [felsorolás_típus_1] of array[felsorolás_típus_2] of... of array [felsorolás_típus_n] of típusnév. A tömb elemeire való hivatkozás lehetséges formái: a[1,2,3,12,5,9,...] vagy a[1][2][3][12]....
A memória dinamikus elérését dinamikus tömbök segítségével is megtehetjük, ezt az Object Pascal a Delphi 4 verziótól kezdve támogatja. A dinamikus tömbök méretét nem a fordítás, hanem a futtatás közben adhatjuk meg. Az egyszerű, egydimenziós dinamikus tömb deklarációja csak a tömb nevét és típusát tartalmazza:
A deklaráció során csak egy mutató jön létre, magát a tömböt futás közben a SetLength() eljárás segítségével hozhatjuk létre, pl:
Ezen utasítás hatására létrejön a 10 darab egész elemet tartalmazó tömb, melynek elemeire ugyanúgy hivatkozhatunk, mint statikus esetben. A tömb csupa 0-t fog tartalmazni. A SetLength() eljárást nem csak létrehozásra, hanem átméretezésre is használhatjuk, ekkor a tömb értékei megmaradnak bővítés esetén. A Copy utasítás segítségével egy dinamikus tömb adott indexű elemétől kezdődően, megadott számú elemet átmásolhatunk egy új dinamikus tömbbe. Azonos típusú dinamikus tömbök között értelmezett az értékadás művelete is, melyen eredménye az lesz, hogy a bal oldalon álló dinamikus tömb mutatója ugyanoda fog mutatni, mint a jobb oldalon álló dinamikus tömbé. Dinamikus tömbök esetében a Length() függvény a tömb elemeinek számát adja vissza. Lekérdezhetjük még a az alsó és felső indexhatárt a Low() illetve a High() függvény segítségével. Az alsó indexhatár mindig 0, üres tömb esetén a felső indexhatár-1. A dinamikus tömbök felszabadításáról referenciaszámláló mechanizmus gondoskodik. A felszabadítást kikényszeríthetjük az alábbi módokon: nil –re állítjuk a tömböt, SetLength() segítségével 0 hosszúvá tesszük a tömböt, vagy a Finalize eljárás meghívásával.
Többdimenziós dinamikus tömböket dinamikus tömbök dinamikus tömbjeként állíthatunk elő, pl:
A SetLength() eljáráshívásban ekkor meg lehet adni mind a két kiterjedést. Ugyanakkor többdimenziós esetben lépésenként is megadhatjuk a tömb méreteit, így ’kesztyűszerű’ tömböket is létre tudunk hozni, pl:
Többdimenziós tömbök törlése ugyanúgy történhet, mint az egydimenziós esetben.
Ez egy tipikusan Pascal típus. Egy új file adattípust a következő sorral definiálhatunk:
Ezután a MyFile változót hozzárendelhetjük egy fizikai állományhoz, majd értékeket olvashatunk belőle, vagy írhatunk bele.
Létezik típus nélküli fájl típus is (file). Ezeknek a fájloknak kézzel kell beállítanunk egy rekordméretet, valamint blokkosan olvashatjuk rekordonkénti olvasás helyett. A standard könyvtár tartalmaz egy TextFile (Pascalban Text) típust, amellyel karakterenként vagy soronként kezelhetünk szöveges fájlokat.
A Delphiben a stringek kezelése ugyanolyan egyszerű, mint Pascalban volt. A hagyományos Pascal stringen kívül a Delphi bevezet két új string típust is: a Windows rendszerrutinok által használt "C-típusú" nullával lezárt stringet, illetve az alapértelmezett hosszú string típust. Ebben a pontban sorra vesszük ezeket, és megnézzük a köztük lévő különbségeket, használatuk alapjait, és a velük kapcsolatos problémákat.
A Pascalhoz hasonlóan a Delphi 16 bites verziójában is a string adattípus egy karaktersorozat, amely a string nulladik elemében (első bájt) tárolja a string hosszát. Az ilyen stringek fix méretűek, maximálisan 255 karakter hosszúak. Ez a legjelentősebb hátrányuk. A string hasonlóan viselkedik a tömb típushoz, ezért is hivatkozhatunk a string egyes elemeire szögletes zárójelek közötti indexeléssel:
Ezen deklaráció mellett írhatjuk a következőt:
A hagyományos string hátrányainak kiküszöbölése érdekében a 32 bites Delphi három új stringet vezetett be:
Figyelem: különböző Delphi verziók esetén eltérő lehet az alapértelmezett karakter mérete, így elromolhatnak olyan régi kódok, amelyek a string típust használják és feltételezik, hogy a karakterek mérete 1 bájt.
A dinamikus memóriafoglalás nem csak a méret növelhetőségét jelenti, hanem azt is, hogy ha egy stringet megduplázunk, akkor az új string helyett csak egy mutató másolódik le, amely az eredeti stringre mutat. Ha bármelyik stringet megváltoztatjuk, akkor az egész string megduplázódik. A Delphi a hosszú stringjeit hivatkozásszámlálási mechanizmussal kezeli, azaz számon tartja, hogy az egyes stringekre hány változó hivatkozik. Amikor ez a szám nullára csökken, a string által lefoglalt memóriát a rendszer felszabadítja.
Amikor egy string méretét növeljük, és az már nem fér el az adott helyén, akkor a teljes string átmásolódik egy nagyobb helyre. Ez időigényes művelet, ezért lehetőségünk van a string számára megfelelő nagyságú memóriát előre lefoglalni: (Ez különösen fontos, ha a stringet egy API függvénynek adjuk át a megfelelő konvertálás után.)
A 32 bites Delphi String típusa a $H fordítási direktívától függően ShortString ($H-) vagy ANSIString / UnicodeString ($H+ alapbeállítás).
A hosszú stringek elemeire is indexeléssel hivatkozhatunk, első elemre az egyes indexszel. Van azonban egy különbség. Míg a hagyományos Pascal stringek méretét lekérdezhettük (sőt be is állíthattuk,) a string nulladik elemén keresztül, erre hosszú stringek esetén nincs mód. (Egyszerűen azért, mert a méret nincs a nulladik elemben eltárolva.) Ehelyett használjuk a Length függvényt a méret lekérdezésére, a SetLength eljárást pedig a méret beállítására.
Ez igazából egy karakterre (karakter sorozatra) mutató pointer (^AnsiChar vagy ^WideChar), úgy is fogalmazhatunk, hogy ez úgynevezett "C-típusú" string. Ez azért lényeges, mert számos Windows API függvény PChar típusú paramétert feltételez. Ahhoz, hogy egy eljárásnak átadjunk egy ilyen típusú változót, először memóriát kell foglalnunk számára a GetMem vagy a NewStr függvénnyel. (Ez esetben ne felejtsük el a memóriát felszabadítani a Dispose eljárással, ha már nincs szükségünk rá.)
Delphiben a nulla indexhatárú karaktertömbök kompatibilisek (ha az "extended language syntax" engedélyezve van - alapbeállítás) a PChar típussal, így egyszerűen hozhatunk létre ilyen típusú stringeket:
Ezután ezt a tömböt feltöltjük, majd tetszőleges API függvénynek átadhatjuk. (Természetesen a string végét 0-nak kell zárnia.) Nullavégű stringekre csak a SysUtils-ban definiált stringkezelő függvényeket használhatjuk ( pl. := helyett StrCopy ). Ilyen stringek használatakor az X direktívának bekapcsolt állapotban kell lennie.
Harmadik, és talán legegyszerűbb módszer a Delphi hosszú stringek használata. Ezek nullával lezárt stringek, ezért kompatibilisek a Windows "C-típusú" stringjeivel. Amennyiben egy hosszú Pascal stringet szeretnénk PChar típusúvá konvertálni, (pl. egy API függvény paramétereként) típusmegfeleltetést kell alkalmazni. Az ellentétes irányú konverzióhoz még ez sem szükséges.
A fenti konverzió működik, ám mégis léphetnek fel problémák. Ez azért lehetséges, mert az átalakítás után a Delphi nem kezeli a stringet, annak tartalmáért mi felelünk. Módosítsuk az előző példát! Szúrjunk be a következő sort az API függvényhívás után:
Ha újrafordítás után futtatjuk a programot, azt tapasztaljuk, hogy az editboxban csak a form fejléce látszik (mint az előbb). Mi is történt itt? Amikor a Windows a stringbe írt, nem állította be a Delphi hosszú string hosszúságát. (A nulla lezárást persze megfelelően kezelte.) Ennek ellenére a Delphi megtalálja a string végét a nulla byte miatt, de a megfelelő hosszt ő sem állítja be, hisz konvertálás után nem felel a stringért. Így amit a string után írtunk, az a nulla lezárás után került, ezért nem íródott ki. Persze a problémának van megoldása. A Delphit utasítani kell, hogy az API függvény által visszaadott stringet konvertálja Pascal hosszú stringgé. (Azaz állítsa be a hosszúságát a valóságnak megfelelően.) Ha azonban a következő sorral próbálkozunk:
akkor semmi sem történik, mert ezt a sort a fordító figyelmen kívül hagyja, mondván egy típust a saját típusába konvertálni felesleges dolog, ezért a stringet ezért PCharrá alakítjuk, majd azt vissza Pascal stringgé:
A string átalakítás el is hagyható, mert a PChar - String konverzió automatikus a Delphiben, azaz a végső megoldás:
A Delphiben a rekord a szokásos:
A tagokat a . operátorral érhetjük el:
A rekordokra értelmezett az értékadás. Név szerinti ekvivalencia vonatkozik rájuk. Nem adható paraméter a rekordnak. A kezdőérték szintaxisa az alábbi:
Ez a szintaxis csak változó és konstans deklarásakor használható, utasításban nem. A Pascal egy egyedi lehetősége, hogy a with rekord do utasítás szerkezettel az utasításban úgy használhatjuk a rekord mezőit, mintha azok lokális változók lennének:
Ez főleg akkor hasznos, ha a rekord egy bonyolult kifejezéssel érhető csak el.
A Delphi az {$A} direktíva állapotától függően igazítja a rekord mezőit, hogy gyorsabb legyen az elérés. Ha nem szeretnénk állítani a direktívát, de egy adott rekordtípus esetén szükséges az igazítás kikapcsolása (pl. hálózati kommunikáció), akkor packed record-ként definiáljuk.
Az újabb Delphi verziókban a rekordoknak lehetnek osztályjellegű tulajdonságai: konstruktorai, metódusai, jellemzői (property), ezek „osztály”-szintű megfelelői, valamint beágyazott típusai. Viszont ettől nem válnak valódi osztállyá, pl. megmarad az érték szerinti átadás, a konstruktor nélküli létrehozás, operátor-túlterhelés, a variáns rekord (ld. unió típus) lehetősége, és nem támogatják az öröklődést, virtuális metódusokat, a destruktorokat és az interfészek megvalósítását.
A rekordok egy speciális tulajdonsága, hogy tartalmazhatnak variáns részt, ezáltal unió típust valósítanak meg. Az uniónak megadható szétválasztó mező, de ennek ellenére mindig elérhetjük az unió összes ágát.
A Delphiben a halmaz nyelvi elemként is létezik. Csak olyan típusból lehet halmazt készíteni, amely felsorolás típus, azaz rákövetkezési relációval bír.
Hátránya: maximum 256 db eleme lehet, és ezek sorszámának a 0..255 intervallumba kell esnie.
Példa:
A két eljárás használatával egyszerűen megoldható a halmazhoz egy elem hozzáadása (Include) vagy egy elem elvétele (Exclude). A két eljárás paramétere egy T típusú halmaz, valamint egy T típussal kompatibilis kifejezés (pl. Include(h,'a')).
Halmaz típusú konstanst a halmazkonstruktor segítségével állítunk elő: szögletes zárójelek között vesszővel elválasztva felsoroljuk a halmaz elemeit. Az egyes elemek mellett intervallumok is szerepelhetnek benne.
Az Object Pascal erősen típusos nyelv, így alapértelmezésben nincs lehetőség típuskonverzióra. Ha azonban mégis erre lenne szükség, két lehetőség kínálkozik:
Az egyik, hogy a szabványos könyvtári függvények segítségével végezzük el az átalakítást, pl:
round() // valós -> egész
trunc() // valós -> egész
ord() // char -> egész
chr() // egész -> char
A másik lehetőség, hogy explicit típuskényszerítést használunk, amely ránézésre olyan, mintha a típus nevét használnánk függvényként. Ez a módszer csak akkor működik, ha az érték és a kívánt típus azonos méretű, és nem keverjük az egész és valós számokat (arra ott vannak a könyvtári függvények).
Integer('A');
Két típus azonos, ha egy típusazonosító egy másik típusazonosítóval van definiálva:
Itt T1, T2, T3, T4 és Integer ugyanazt a típust jelölik. A típuskonstrukciók különböző típusokat hoznak létre még akkor is, ha ugyanaz a konstrukció:
TS1 és TS2 különböző típusok, valamint S1 és S2 különböző típusú változók. Két azonos típusú változót így hozhatunk létre:
vagy:
Változó és konstans csak az eljárások, függvények deklarációs részében, valamint a globális hatáskörben definiálható. Változóra láthattunk példákat a fenti kódrészletekben.
Konstans definiálása: a const kulcsszó után tetszőleges kifejezés megadható, amelynek típusa egyértelmű és a fordítás pillanatában kiértékelhető, vagy mi magunk is megadhatjuk a típust:
Bizonyos beépített függvények használhatók konstans kifejezések megadásában (lásd E változó): Abs, High, Low, Pred, Succ, Chr, Length, Odd, Round, Swap, Hi, Lo Ord, SizeOf, Trunc. Kétféle konstans létezik: valódi konstans (<név> = <érték>) és típusos konstans (<név> : <típus> = <érték>). Minden valódi konstans fordításkor szövegszerűen helyettesítődik az értékével, míg a típusos konstans értéke megváltoztatható, ha a {$J+} fordítói direktíva adott (nem javasolt, csak visszafelé kompatibilitás miatt van). A változóknak is adható kezdőérték a típusos konstans szintaxisával.
Stringek esetén van egy további lehetőségünk: a resourcestring részben deklarált konstansok a Windows végrehajtható fájl erőforrás (resource) részében kapnak helyet, így a program többi részének újrafordítása nélkül is megváltoztathatók.
not, and, or, xor. Az and és or kiértékelése a $B direktívától függ: {$B-} állapotban (alapértelmezés) a kiértékelés rövidzáras, {$B+} állapotban teljes. Ez alól kivétel, ha az egyik argumentum Variant típusú: ekkor mindenképpen teljesen kiértékelődik a kifejezés.
=, <>, <, >, <=, >=. Fontos megjegyezni, hogy az összehasonlító operátorok precedenciája itt alacsonyabb, mint a logikai műveleteké (a Delphiben csak 4 precedenciaszint van), így pl. az a = b and c > d helytelen kifejezés, (a = b) and (c > d) alakban kell leírni.
A halmaz típus bír annak a szokásos műveleteivel: in (eleme-e), + (unió), -(különbség), * (metszet), illetve lehet halmazok egyenlőségét lekérdezni (=), és van halmazok közti <=, >=, <> (A <= B igaz, ha A részhalmaza B-nek).
A stringekre értelmezettek az összehasonlító műveletek (lexikografikus rendezés karakterkód szerint), valamint a +, amely konkatenációt jelent. Stringet lehet konkatenálni karakterrel, de ha az WideChar, akkor a string csak AnsiString, UnicodeString vagy WideString lehet. Ha a konkatenáció eredménye hosszabb, mint 255, és ShortString-nek akarjuk értékül adni, akkor a string csonkolódik. Nem lehet stringhez számot stb. konkatenálni (csak explicit konverziós függvényekkel).
A @ prefix operátor egy tetszőleges változó, eljárás, függvény vagy metódus esetén visszaad egy pointert, amely az adott dologra mutat. Változó esetén visszaadja a változó címét, típusa a {$T-} (alapértelmezett) állapotban Pointer, {$T+} állapotban a változó típusának megfelelő pointer. Eljárás, függvény, metódus (ez utóbbi esetén kötelező kiírni az osztály nevét) esetén a visszaadott pointer az alprogram belépési pontjára mutat, típusa Pointer.
Osztályokra értelmezett két operátor. Az objektum is Osztály kifejezés megmondja, hogy egy objektum az adott osztályból (vagy egy leszármazottjából) való-e. Az as egy objektumot konvertál a megadott osztály vagy interfész típusra ellenőrzéssel: ha az ellenőrzés sikertelen, kivétel váltódik ki.