Forrásszöveg-modulok
Ezek lehetnek makrók, vagy include-ok. A makrók a C-ből lettek átvéve. Az include-ok esetében
a benne található forrásszöveg bemásolódik a program azon részére, ahol a megfelelő parancsot kiadjuk..
Alprogramok
Ezek hasonlítanak a C-beli void függvényekhez, vagy a Pascal-ban megszokott eljárásokhoz.
Az utasítás formája:
FORM <form neve>
[TABLES <formális paraméterek> ...]
[USING <formális paraméterek> ...]
[USING VALUE(<formális paraméter>) ...]
[CHANGING <formális paraméterek> ...]
[CHANGING VALUE(<formális paraméter>) ...].
<végrehajtási blokk>
ENDFORM.
Minden esetben engedélyezett a tipizálás. Ez esetben a formális paraméter után egyszerűen csak a
TYPE,
vagy a
LIKE kulcsszót kell írni, majd a típust ill. az objektumazonosítót. Egy form meghívásánál
a rendszer megvizsgálja a tipizált formális és az aktuális paraméter típuskompatibilitását.
Ezen szabályok egy rendszertáblában vannak leírva. Ha nem megfeleltethető egymásnak a két típus,
akkor hibaüzenetet kapunk. Típuskonverzió ezen a helyen nem történik.
A
TABLES kulcsszó után szerepelnek az alprogram részére
cím szerint átadott táblák.
Ha nem tipizáljuk, akkor a táblának csak a teljes soraihoz férhetünk hozzá és az egyes mezőkhöz nem.
A
USING és
CHANGING segítségével mezőket és összetett struktúrákat adhatunk át ugyancsak
cím szerint, tehát a változtatások közvetlen a főprogrambeli változót érintik. A különbség a kéttő
között pusztán dokumentációs jellegű.
USING esetén olyan változókat adjunk át, amiket az alprogram
nem változtat meg a futása során és a
CHANGING paraméterében olyan mezők szerepeljenek melyekbe
írunk is. Érdekes a
VALUE használata a két szekcióban. A
CHANGING-ben átadott paraméterről
készül egy lokális másolat, de csak akkor kerül az érték a globális változóba, ha az alprogram lefutása
hibamentes volt. Így tehát elkerülhetjük az inkonzisztens állapotot a programunkban. Ha
érték
szerint akarunk egy paramétert átadni, akkor használjuk a
USING szekcióban a
VALUE(...) alakot.
Itt felülírhatjuk a változó értékét anélkül, hogy az eredeti paraméterre hatással lennénk.
Aktuális paraméterként átadhatunk konstansokat, vagy literálokat is, de ez esetben a változóba történő írásnál
a program a
MOVE_TO_LIT_NOTALLOWED futásidejű hibaüzenettel leáll.
Megkülönböztetünk lokális és globális változókat az alábbiak szerint:
- Láthatóság
- -
- globális: a program teljes területén hivatkozhatunk rá
- -
- lokális: csak a formban elérhető
- Élettartam
- -
- statikus: a program futása végéig él
- -
- temporális: élettartama a form élettartamára korlátozódik
Külső (más programban implementált) formok meghívása esetén szükség lehet közös adatterületek
definiálására. Ekkor a közös adatterületet a hívott formnak a programja is, és a hívó program is látja.
Ennek deklarálása a
DATA utasítással történik. Szokás a közös adatterületeket egy include file-ba
tenni és a megfelelő programokba ezeket befűzni.
A fentebb definiált formokat az alábbi utasítással hívhatjuk meg:
PERFORM <form neve>[(<melyik programból>)]
[TABLES <aktuális paraméterek> ...]
[USING <aktuális paraméterek> ...]
[CHANGING <aktuális paraméterek> ...]
[IF FOUND].
Ha nem az aktuális programban található a form, akkor a neve után meg kell adni, hogy melyik programban
található meg a form törzse. Ilyen külső hívásnál alkalmazható a
IF FOUND is. Ekkor ha a rendszer
nem találja a formot a programban, akkor egyszerűen nem hajtja végre azt. A fenti deklaráció esetében
a program nevének fordítási időben rendelkezésre kell állni. Amennyiben az csak futásidőben deríthető
ki , úgy a
PERFORM (<
form neve>) [
IN PROGRAM (<
melyik programból>)] [...] [
IF FOUND].
alakot használjuk.
A behelyettesítések az egyes szekciókban a sorrendnek megfelelően történnek.
példa kód:
*eljárások bemutatása
*segéd változók, végig jegyezzük meg az értéküket
DATA: a TYPE i VALUE 1,
b TYPE i VALUE 2,
c TYPE i,
d TYPE c.
*egy sima paraméter néküli eljárás hívás
PERFORM header.
*a kezdeti változók kiíratása
* a=1, b=2, c=0
WRITE: / a, b, c.
*referencia alapján adtuk át a változókat, így
* a=1001, b=2, c=3
PERFORM computing_ref USING a b c.
WRITE: / a, b, c.
*értékszerinti paraméterátadás
* a=1001, b=2, c=1003
PERFORM computing_val USING a b c.
WRITE: / a, b, c.
c = 0.
PERFORM check USING c.
c = 1.
PERFORM check USING c.
*a paraméter nélküli eljárás definíciója
FORM header.
WRITE: / 'Program started by', sy-uname,
/ 'on host', sy-host,
'date:', sy-datum, 'time:', sy-uzeit.
ULINE.
ENDFORM.
*refenrencia szerinti paraméterátadás
*itt p3, és p1 értéke is változik, (kivül)
FORM computing_ref USING p1 p2 CHANGING p3.
p3 = p1 + p2.
p1 = p1 + 1000.
ENDFORM.
*értékszerinti
*elvileg kivül semelyik változó értékének nem kéne megváltoznia, de
*a CHANGING kulcszsó hatásará mégis bemásolja a megváltozott értéket a p3 esetében
FORM computing_val USING VALUE(p1) VALUE(p2) CHANGING VALUE(p3).
p3 = p1 + p2.
p1 = p1 + 1000.
ENDFORM.
*előfeltétel ellenőrzése:
*leellenörzi, hogy, hogy a p1 értéke nulla-e, ha igen akkor le se fut
*ha nem nulla akkor végrehajtja az utasításokat
*az EXIT-el pedig értelemszerűen kiszállhatunk
FORM check USING p1.
CHECK p1 <> 0.
WRITE: / c, 'a', 'b'.
EXIT.
WRITE / 'c'.
ENDFORM.
Függvénykönytárak
A függvényekkel további lehetőségünk van a programunkat struktúrálttá tenni. Vannak előre megírt
rendszerfüggvények, de mi magunk is létrehozhatunk saját függvényeket. A megfelelő menü meghívása
után meg kell adnunk az IMPORT, az EXPORT a CHANGING, a TABLES
valamint az EXCEPTION paramétereket. Ilyenkor a kódban szokás a jobb olvashatóság érdekében
a paraméterek neve elé a paraméter típusára vonatkozó rövidítést használni: pl. az I_par
egy IMPORT paramétert akar jelenteni. A kivételkezelésről külön fejezetben lesz szó.
Ezek után a függvényhez az ABAP/4 generál egy kommentárt (Local interface), mely leírja,
hogy milyen paraméterekkel hívható meg a függvény. Ezen kommentárt manuálisan ne változtassuk.
Egy már létező függvényt az alábbi utasítással hívhatunk meg:
CALL FUNCTION <függvény neve>
[EXPORTING <formális paraméter>=<aktuális paraméter> ...]
[IMPORTING <formális paraméter>=<aktuális paraméter> ...]
[CHANGING <formális paraméter>=<aktuális paraméter> ...]
[TABLES <formális paraméter>=<aktuális paraméter> ...]
[EXCEPTIONS <formális paraméter>=<aktuális paraméter> ...
[ERROR_MESSAGE=<aktuális paraméter>]
[OTHERS=<aktuális paraméter>]].
példa kód:
*egy példa a függvényhívásra
*ide kerül a válasz, eredmény
DATA: ans TYPE string.
*az EXPORTING részben soroljuk fel a paraméter(eke)t
*az IMPORTING részben pedig a visszatérési értéke(ke)t
*az EXCEPTIONS -ben pedig számszerűsíthetjük a kivételeket
CALL FUNCTION 'Z_PRIM'
EXPORTING
parameter = -6
IMPORTING
answer = ans
EXCEPTIONS
NOT_POSITIVE = 1.
*a hívás után változik a sy-subrc értéke
*0 ha nem történt kivétel, egyéb ha igen, és az amit mi adtunk meg
*ezt a legegyszerűbb egy CASE-WHEN rendszerrel lekezelni
CASE SY-SUBRC.
WHEN 1.
WRITE / 'Az input csak pozitív szám lehet!'.
ENDCASE.
WRITE / ans.
*a függvény modul
FUNCTION Z_PRIM.
*generált információk
*"----------------------------------------------------------------------
*"*"Local interface:
*" IMPORTING
*" REFERENCE(PARAMETER) TYPE I
*" EXPORTING
*" REFERENCE(ANSWER) TYPE STRING
*" EXCEPTIONS
*" NOT_POSITIVE
*"----------------------------------------------------------------------
*kivétel kiváltodása, és "dobása"
IF parameter <= 0.
RAISE NOT_POSITIVE.
ENDIF.
DATA: tmp TYPE i VALUE 2,
tmp2 TYPE i.
Függvénycsoportok
A függvényeket összefoghatjuk bizonyos tulajdonságaik alapján (pl. azonos táblán dolgoznak) és egy un.
függvénycsoportba tárolhajtuk, ahol deklarálhatunk melléjük globális adatokat, közös formokat.
Egy függvénycsoport jól struktúráltan tartalmazza az összes függvényhez tartozó adatokat, közös alprogramokat.