ProgramozásMódszertan
2. előadás’2005
(vázlat)

1. A modul mint a típusmegvalósítás kerete

1.1 Mi a típus?

Amit már tudunk – „statikus kellékek

Miket kell megadni ahhoz, hogy mondhassuk: a típust „teljesen” ismerjük?

A statikus kellékeken, ismereteken túl:

Mit értünk a típus megvalósítása alatt?

Annak definiálását, hogy milyen leképezést valósítanak meg az egyes műveletek (szemanti­ka-definíció), és hogyan lehet „megszólítani” őket (szintaktika-definíció):

  1. Definiálhatjuk csak a kapcsolatukat, egymásra hatásukat, axiómák megadásával. (Al­gebrai specifikáció)
  2. Definiálhatjuk az egyes műveletek „egyedileképezésének megadásával. Ez az export modul feladata, amely tartalmazza a szignatúrákat és –esetleg– az elő-utófeltételeket. (Algoritmikus specifikáció)
  3. Rögzíthetjük az egyes műveleteket „egyedimegvalósításukkal, amelyben már figye­lembe vesszük a típus már rögzített ábrázolását. Ez a reprezentációs-implementációs modul feladata.

A fenti 2-3.-at egyaránt vonatkoztathatjuk algoritmusra és konkrét programozási nyelvre. A következő („1.3. A modul”) fejezetben mi az algoritmikus nyelvünket bővítjük ki úgy, hogy kezelhető legyen benne e kérdéskör. Mivel nem állunk meg a puszta elmélet síkján tisztázzuk azt is („2. A modulfogalom és a Pascal nyelv” fejezetben), hogy az általunk használt lingua franca, a Pascal programozási nyelv, milyen lehetőséget ad mindehhez.

1.2. A típus algebrai specifikációjáról

Röviden utalunk a nyelv azon kiegészítésére, amelyben tisztázni fogjuk „globális” elvárásain­kat az adott típussal szemben. Ezt a legabsztraktabb elképzelést formálisan egy algebrai alapú nyelven írjuk le, az alábbi keretben:

Szintaktikai „minta”

Magyarázat

Típus TípusKonstrukció(paraméterek):

Asszociált műveletek:

 Operáció(értelmezési tartomány): Értékkészlet

 

 

 

A definiálandó típuskon­strukció „alkalmazási sablona” (feje).

Operációinak szignatú­rája (értelmezési tartomá­nya, értékkészlete)

Axiómák:

 Jelölések:

  objektum: Típus(paraméterek) =
                        értelmező megjegyzés

 

1o az axióma informális szövege ...

  a formalizált axióma

2o

 

Az operációk kapcsolatát leíró axiómák, és a ben­nük fölhasznált objektu­mok „deklarációi”.


Axióma-állítások esetleg kibővítve fontos következ­ményállításokkal.

Mint a példából is kiderül alkalmazunk néhány konvenciót, amelyet most –az idő rövidsége miatt– nem taglalunk. (A részletekhez lásd a Típus-specifikációkban.)

Visszatérő példa legyen a hét napjainak típusa! Nézzük ennek egy lehetséges algebrai leírását! Megjegyzem: a példa nem „tipikus” bizonyos értelemben, mivel a napok típusa egy konkrét típus, így nem tudunk élni a fenti típus-specifikálási „nyelvezet” paraméterezési szolgáltatá­saival.

Példa:

Típus TNap:

Asszociált műveletek:

 Hétfő,Kedd,Szerda,Csütörtök,
 Péntek,Szombat,Vasárnap,
 Min,Max:TNap
 Számosság:Egész
[1]

 Létrehoz:TNap
 Lerombol(TNap)
 Következő(TNap):TNap
È {NemDef}
 Előző(TNap):TNap
È {NemDef}
 Sorszám(TNap):Egész
 TNap(Egész):TNap
È {NemDef}
 <(TNap,TNap):Logikai

Axiómák:

a:TNap

n:Egész

0o A minimális érték a Hétfő, a maximális a Vasárnap, a típus számossága 7.

   Számosság=7  Ù  Min=Hétfő  Ù  Max=Vasárnap

1o Létrehozás utáni értéke Hétfő.

   a=Létrehoz Þ a=Hétfő

2o Lerombolás után nincs értelme a műveletek (a Létrehoz kivételével) alkalmazásának.

   Következő(Lerombol(a))=NemDef  Ù 

3o Nem létezik Hétfőt megelőző, s Vasárnapot követő.

   Előző(Hétfő)=NemDef Ù Következő(Vasárnap)=NemDef

4o A Következő és Előző műveletek egymás inverzei.

   $Előző(a) Þ Következő(Előző(a))=a  Ù

   $Következő(a) Þ Előző(Következő(a))=a

5o A Sorszám és TNap műveletek egymás inverzei.

   nÎ[0..Számosság) Þ Sorszám(TNap(n))=n  Ù
                    TNap(Sorszám(a))
=a  Ù
n
Ï[0..Számosság) Þ TNap(n)=NemDef

6o A fenti felsorolás sorrendjében növekvően rendezettek.

   Következő(Hétfő)=Kedd  Ù  Következő(Kedd)=Szerda …

7o A Hétfő sorszáma 0, a Vasárnapé 6.

   Sorszám(Hétfő)=0  Ù  Sorszám(Vasárnap)=6

Állítás: Sorszám(a)Î[0..Számosság); és a

  Sorszám(a)=a fenti felsorolásbeli pozíciója + 1.

Bizonyítás:

  Nyilvánvaló.

8o A felsorolásban előbb szereplő kisebb, mint bármely
későbbi.

   a<b  Û  Sorszám(a)<Sorszám(b)[2]

 

Megjegyzések:

1.3. A modul

Elsőként a programozói felületet leíró, ún. export modul szintaxisát adjuk meg:

ExportModul TípusNév(InputParaméterek):

   [most következnek az exportálandó fogalmak „értelmes” csoportosításban:]

  Típus  [ritkán van ilyenre szükség]
    Tip1,Tip2,... [csak azonosítók felsorolása!]

  Konstans  [ritkán van ilyenre szükség]
    Kons1,Kons2,...[a TípusNév típus néhány kiemelendő konstansa]

  [az alábbi részben soroljuk föl a típushoz tartozó tevékenységek „fejsorait”
   és működésüket leíró elő-utófeltételeket]

  Függvény Fv1(FormParam): FvTip1
    Ef: …
    Uf: …
  Függvény Fv2(FormParam): FvTip2
    Ef: …
    Uf: …
 

  Eljárás Elj1(FormParam)
    Ef: …
    Uf: …
  Eljárás  Elj2(FormParam)
    Ef: …
    Uf: …
 

  Operátor Op1(FormParam): OpTip1
    Ef: …
    Uf: …
  Operátor Op2(FormParam): OpTip2
    Ef: …
    Uf: …
  

Modul vége.

Megjegyzések:

Példa:

ExportModul Tömb(Típus TIndex: Típus TElem):

Modul vége.

  A fenti definíció után a felhasználás szintaxisa:


Típus
 Vektor=Tömb(1..9:Egész)

Ki fogjuk egészíteni az algebrai specifikáció műveletkészletét továbbiakkal is: egyenlőség-vizsgálattal, értékadással, beolvasás és kiírás műveletekkel, valamint a hibás elvégzés tényét rögzítő hiba-flag-et kezelő függvénnyel. (Ezek nélkül ugyanis felhasználhatatlan eszköz ma­radna a legtöbb típus, vagy mindenegyes esetben a programozónak külön kellene jól-rosszul ezen műveletekkel kiegészítenie.) Mindezt annak ellenére tesszük, hogy sok esetben a progra­mozási nyelvek nem adnak mindegyikre (pl. a „típusos” be/ki-re) módot.

Egy-két típusnál szokatlan lehet valamely létrehozó, ill. leromboló művelet használatának ex­plicit felkínálása, mivel a programozási nyelvek legtöbb implementációja automatikusan gon­doskodik a létrehozásról. (Pl. Tömb, Táblázat, Statikus gráf.) A leírás teljességére való törekvés, illetve az esetleges „hagyományostól” eltérő ábrázolás lehetővé tétele mégis in­dokolttá tehetik ezt.

Nézzük visszatérő példánk egy lehetséges export modulját!

Példa:

ExportModul TNap: [kiindulási alap az algebrai leírás]
  Konstans
    Hétfő, Kedd, Szerda, Csütörtök, Péntek, Szombat,
   
Vasárnap:TNap

  Operátor Min:TNap
    Másnéven Min’TNap
    Ef: –
    Uf: Min=Hétfő

  Operátor Max:TNap
    Másnéven Max’TNap
    Ef: –
    Uf: Max=Vasárnap

  Operátor Számosság:Egész
    Másnéven Számosság’TNap
    Ef: –
    Uf: Számosság=7

  Függvény Következő(Változó x:TNap):TNap[SzP1] 
    Ef: x¹Vasárnap [v.ö. a 3. axiómával]
    Uf: Következő(Hétfő)=Kedd  Ù    [v.ö. a 6. axiómával]

  Függvény Előző(Változó x:TNap):TNap
    Ef: x¹Hétfő [v.ö. a 3. axiómával]
    Uf: Előző(Kedd)=Hétfő  Ù    [v.ö. a 6.&4. axiómával]

  Függvény Sorszám(Konstans x:TNap):Egész
    Ef: –
    Uf: Sorszám(Hétfő)=0  Ù  [v.ö. a 7. axiómával]

  Függvény TNap(Változó x:Egész):TNap
    Ef: xÎ[0..6]
    Uf: TNap(0)=Hétfő  Ù 

  Infix Operátor Egyenlő(Konstans x,y:TNap):Logikai
    Másnéven x=y
    [ezt a függvényt nem specifikáljuk, mert az „alapokat” firtatja, és
     elkerülhetetlenül circulum viciosus-ba ütköznénk]

  Infix Operátor LegyenEgyenlő(Változó x:TNap
                               Konstans y:TNap)
    Másnéven x:=y
    [ezt az eljárást nem specifikáljuk, mert az „alapokat” firtatja, és
     elkerülhetetlenül circulum viciosus-ba ütköznénk]

  Infix Operátor Kisebb(Konstans x,y:TNap):Logikai
    Másnéven x<y
    Ef: –
    Uf: Kisebb(Hétfő,y)  Û  y¹Hétfő  Ù 
        

  Operátor Be(Változó x:TNap)
    Másnéven Be:x
    Ef: InputÎ{’hétfő’,’kedd’,’szerda’…}
    Uf: Input=’hétfő’  Þ  x=Hétfő  Ù 

  Operátor Ki(Konstans x:TNap)
    Másnéven Ki:x
    Ef: –
    Uf: x=Hétfő  Þ  Output=’hétfő’  Ù 

  Függvény Hibás?(Változó x:TNap):Logikai
   [teszteli, hogy volt-e hibásan elvégzett művelet (pl. amelynek

    az előfeltétele nem teljesült) az adott TNap típusú (x) adatra;

    majd inicializálódik a hiba-flag]

Modul vége.

Megjegyzések:

·        A Létrehoz és Lerombol műveleteket kihagytuk az algoritmikus specifikációból. Ezzel eltértünk az algebrai specifikációtól. Ok: statikusan kívánjuk megvalósítani e felsorolástípust, építünk a blokk-struktúrájú nyelvek adatlétrehozó, -leromboló mecha­nizmusainak létére. (Gondoljon az eljárás-/függvény-paraméterekre és a lokális adatok kezelésére!) A Létrehoz-axióma persze még fel kell bukkanjon a megvalósításban a szükséges kezdőérték megadása miatt.

·        A Min, Max és Számosság konstansokat (prefix) 0-változós operátorként defi­niáltuk, s nem konstansként, mert alkalmazásuk speciális szintaxisú (típusparaméterű). Vegyük észre, hogy ezek a konstansok minden rendezett, illetőleg véges típus esetén értelmesek. Így a használó program szintjén való megkülönböztetés érdekében olyan szintaxist kell hozzájuk rendelni, amely lehetővé teszi a típushoz kapcsolást. Ilyen probléma nem vetődik föl a többi (Hétfő, Kedd stb.), natív konstanssal kapcsolat­ban. (Ez a magyarázata a Min’Típus, Max’Típus, illetve a Számosság’Típus kü­lönleges szintaxisának.)

Példa:


  Változó
    ma:TNap
    napDb:Egész


  Ciklus ma=Min’TNap-tól Max’TNap-ig
  
  Ciklus vége
  napDb:=Számosság’TNap

·        Látható, hogy akkurátusan törekedtünk –bármi áron is!–, hogy az utófeltételekben ne nyúljunk vissza más művelethez, csak saját „hatáskörben” definiáltuk az elvárásokat. Ha ezt az elvet nem tartottuk volna tiszteletben, akkor egyszerűen meg lehetett volna fogalmazni a := és = operátorok utófeltételét. Például:

Egyenlő.Uf: x=y Û Sorszám(x)=Sorszám(y).

Ekkor azonban könnyen előadódhatna az a helyzet, hogy egymásra kölcsönösen hi­vatkozva specifikáljuk őket, ami egy logikailag értelmezhetetlen specifikációt ered­ményezne.

·        Az értékadás és az értékazonosság operációkról feltesszük, hogy bitről-bitre történő másolást, illetőleg azonosságvizsgálatot jelent, ezért nem tartjuk fontosnak feltételek­kel körülbástyázni. Másrészt, ha ezt formálisan is le akarnánk írni, vissza kellene nyúl­ni (esetleg bit-szintű) reprezentációig, amit effajta specifikációnál elkerülendőnek te­kintünk.

·        Az időnként felbukkanó „” folytatás jelzése formálisan megengedhetetlen, azonban itt csupán egy példáról van szó, így megelégedtünk a kitalálható folytatás jelzésével.

·        Fölvethető kérdés: mennyire ugyanarról szól a kétféle specifikáció. Valóban ez külön vizsgálandó, sőt bizonyítandó probléma.

·        A „Be:” és „Ki:” operátorok működésénél két problémát kell tudni formalizálni:

1.      a külvilággal való kapcsolatét (amely karakteres alapú),

2.      SzövegTNap transzformációét.

Az 1. általános megoldására bevezettünk két függvényt. Az Input megadja azt a szö­veget, amelyet a beolvasó utasítás talál az input-pufferben; az Output szimbolizálja az output-puffer állapotát (azt a szöveget, amely kiíródik a végrehajtás során, pl. a képernyőre). Így a 2. probléma már kezelhetővé vált, hisz az adat és transzformáltja is egy-egy memóriabeli objektumban csücsül. Fel kell figyelnünk a szöveges és a „belsőállapotú” konstansok merev megkülönböztetésére (’hétfő’Hétfő…)!

·        Operátornak azt az alprogramot nevezzük, amely az eljárástól vagy függvénytől eltérő szintaxissal építhető be a programba (azaz hívható). Lehet Infix, ekkor a két operandus közé illeszkedik, lehet Prefix, ekkor megelőzi az egyetlen paraméterét, ill. Postfix esetben követi. S lehet „egyéni” szintaxisa, ekkor a Másnéven kulcs-szónál adhatjuk meg ezt. A leggyakoribb eset a Prefix, ezért ezt a minősítőt elhagyhatjuk.

·        Egyik-másik operátornál „meglepő” a paraméter hozzáférési joga. A várható konstans helyett változó lett azért, mert a végrehajtás során hiba következhet be, amely által az „állapota” kényszerűen és szándékunk ellenére megváltozik. (Következő, ElőzőHibás?. Nagyjából azoknál, amelyeknél nem üres az előfeltétel, tehát van „esélye” a hibás használatnak. Pontosan azoknál, amelyeknek bármi köze is van a hiba-flag-hez.)

Folytassuk a megvalósítást betetéző fogalommal, a reprezentációs-implementációs modullal, röviden a modullal! Ennek feladata, hogy amit eddig elterveztünk, azt kidolgozza: azaz tisz­tázza, hogy

  1. miként ábrázolható a típusbeli érték a memóriában, vagy bárhol (reprezentáció) és
  2. hogyan valósíthatók meg az egyes műveletek, figyelembe véve a választott ábrázolást (implementáció).

A modul-szintaxis a következő:

Modul TípusNév(InputParaméterek):

 Reprezentáció

 
  [a típusábrázoláshoz szökséges adatleíró „kellékek”:
   konstansok, saját típusok,
   a változó-deklarációs rész már magának a típusnak a „mezőit” határozza meg]

 Implementáció

  [itt szerepelnek az export-modulban „megjósolt”
   tevékenységek működésének részletezése…]

  Függvény Fv1(FormParam): FvTip1
    Ef: …
    Uf: …
   

  Függvény Fv2(FormParam): FvTip2
    Ef: …
    Uf: …
   

  Eljárás Elj1(FormParam)
    Ef: …
    Uf: …
    

  Eljárás Elj2(FormParam)
    Ef: …
    Uf: …
    

  Operátor Op1(FormParam): OpTip1
    Ef: …
    Uf: …
   

  Operátor Op2(FormParam): OpTip2
    Ef: …
    Uf: …
   

 Inicializálás

  [egy ilyen típusú adat létrehozása az itt leírt utasításokkal történik]

Modul vége.

Megjegyzések:

·        Az egyes műveletek egyedi specifikációját jelentő elő-utófeltétel párok, amennyiben megegyeznek az exportmodulbelivel, nyilván elhagyhatók. Természetesen „értelme­sen” igazítva a reprezentációhoz, újabb biztonsági támpontul szolgálhat a fejlesztés­hez. (Ekkor persze újabb feladatként járul az eddigiek mellé, hogy ezek következését az „elődjükből” be kell látni:
operációExportmodul.Ef Þ operációModul.Ef Ù operációExportmodul.Uf Þ operációModul.Uf.)

A visszatérő példánk egy lehetséges moduljának töredékét tervezzük meg az alábbiakban. A reprezentációs döntésünk, hogy legyen minden TNap adatnak legyen egy hiba-flag-je.

Példa:

Modul TNap: [kiindulási alap az export modul]
 Reprezentáció

   Változó
     felsKód:Egész
     hiba:Logikai

   Konstans
     Hétfő:TNap[SzP2] (0,Hamis)
    
Kedd:TNap(1,Hamis)
    
     Vasárnap:TNap(6,Hamis)

 Implementáció

  Operátor Min:TNap
    Másnéven Min’TNap
    Ef: –
    Uf: Min=Hétfő

    Min:=Hétfő
  Operátor vége.

  Operátor Max:TNap
    Másnéven Min’TNap
    Ef: –
    Uf: Max=Vasárnap

    Max:=Vasárnap
  Operátor vége.

  Operátor Számosság:Egész
    Másnéven Számosság’TNap
    Ef: –
    Uf: Számosság=7

    Számosság:=7
  Operátor vége.

  Függvény Következő(Változó x:TNap):TNap
    Ef: x¹Vasárnap
    Uf: x=Hétfő  Þ Következő(x)=Kedd  Ù

    Ha felsKód=Vasárnap.felsKód

       akkor    hiba:=Igaz
       különben Következő.felsKód:=felsKód+1
  Függvény vége.

  Függvény Előző(Változó x:TNap):TNap
    Ef: felsKód¹Hétfő
    Uf: felsKód=Kedd Þ Előző(x).felsKód=Hétfő  Ù

   
  Függvény vége.

  Függvény Sorszám(Konstans x:TNap):Egész
    Ef: –
    Uf: x.felsKód=Hétfő.felsKód Þ Sorszám(x)=0  Ù

   
  Függvény vége.

  Függvény TNap(Változó x:Egész):TNap
    Ef: xÎ[0..6]
    Uf: TNap(0).felsKód=Hétfő.felsKód  Ù 

    
  Függvény vége.

  Infix Operátor Egyenlő(Konstans x,y:TNap):Logikai
    Másnéven x=y
    [ezt a függvényt nem specifikáljuk, mert az „alapokat” firtatja,
     és elkerülhetetlenül circulum viciosus-ba ütköznénk]
   
  Operátor vége.

  Infix Operátor LegyenEgyenlő(Változó x:TNap
                               Konstans y:TNap)
    Másnéven x:=y
    [ezt a függvényt nem specifikáljuk, mert az „alapokat” firtatja,
     és elkerülhetetlenül circulum viciosus-ba ütköznénk]
    
  Operátor vége.

  Infix Operátor Kisebb(Konstans x,y:TNap):Logikai
    Másnéven x<y
    Ef: –
    Uf: x.felsKód=Hétfő.felsKód Þ Kisebb(x,y)  Û 
        y.felsKód¹Hétfő.felsKód  Ù 
        
   
  Operátor vége.

  Operátor Be(Változó x:TNap):
    Másnéven Be:x
    Ef: InputÎ{’hétfő’,’kedd’,’szerda’…}
    Uf: Input=’hétfő’  Þ  x=Hétfő  Ù 
   
  Operátor vége.

  Operátor Ki(Konstans x:TNap):
    Másnéven Ki:x
    Ef: –
    Uf: x=Hétfő  Þ  Output=’hétfő’  Ù 

   
  Operátor vége.

  Függvény Hibás?(Változó x:TNap):Logikai
    Hibás?:=hiba; hiba:=Hamis
  Függvény vége.

 

 Inicializálás

   hiba:=Hamis; felsKód:=Hétfő

Modul vége.

Megjegyzés:

2. A modulfogalom és a Pascal nyelv

Amire mód van: algoritmikus specifikáció és a megvalósítás; amire nincs: az algebrai specifi­káció. Többféle Pascal-nyelvi lehetőséget lehet a típusgyártás szolgálatába állítani:

Az nyilvánvaló, hogy a Pascal-ban

Algoritmikus

Þ

Pascal

Operátor Min:TNap
  Másnéven Min’TNap
  Min:=Hétfő
Operátor vége.

Þ

Procedure Min(Var minKi:TNap);
Begin
  minKi:=Hetfo
End;

2.1. Unit

·        A unit szintaxisa igazodik a Pascal nyelvhez, így túl sok magyarázatra nincs szükség. Annyit előljáróban: a unit egyesíti az exportmodul (Interface-rész) és a modul (Im­plementation-, inicializáló rész) fogalmat.

Unit TipusNev;{InputParaméterek}

 Interface

 
  {a kívülről láttatandó fogalmak:
   unit-ok, konstansok, típusok, változók; eljárások és függvények fejsorai}
 

 Implementation

 
  {az elrejthető reprezentációs dolgok:
   unit-ok, konstansok, változók, típusok, „saját” eljárások és függvények;
   az exportált eljárások és függvények törzsükkel együtt}
 

Begin

 
  {a típus adatainak inicializálását végző utasítások}
 
End.

Megjegyzések:

Például:  írható saját ClrScr-eljárás, amelyben építhetünk a Crt unit hasonló nevű eljárására:


  Uses
…,Crt,…;
 
  Procedure ClrScr(Const cím:String);
  Begin
    Crt.ClrScr;
    Writeln(cím:40+(Length(cím) Div 2));
   
  End;

Begin

  ClrScr(’Ügyes kis program’);

Az alábbi példa bemutatja, hogyan lehet a TNap típust unit-tal megvalósítani. A Pascal nyelv fentebb említett kellemetlen vonásai miatt a TNap-értékű függvényeket procedure-ákkal kell helyettesíteni.

Példa:

Unit TNapUnit;{InputParaméterek}

 Interface

  Type
    TNapK=(Hetfo,Kedd,Szerda,Csutortok,
           Pentek,Szombat,Vasarnap);
    TNap=Record felsKod:TNapK; hiba:Boolean End;

  Procedure Min(Var minKi:TNap);
    {Ef: –
     Uf: minKi=TNap(Hetfo,Hamis)}

 

  Function Szamossag:Word;
    {Ef: –
     Uf: Szamossag=7}

  Procedure Kovetkezo(Var x:TNap; Var kovetkezoKi:TNap);
    {Ef: x.felsKod<>Vasarnap
     Uf: x.felsKod=Hetfo  Þ KovetkezoKi.felsKod=Kedd  ES…}

 

  {erre nincs szükség, ezt tudja a Pascal (:=):
  Procedure LegyenEgyenlő(Var x:TNap
                          Const y:TNap);
  }

  Function Egyenlo(Const x,y:TNap):Boolean;
    {Ef: …
     Uf: …}

  Function Kisebb(Const x,y:TNap):Boolean;
    {Ef: …
     Uf: …}

  Procedure Be(Var x:TNap);
    {Ef: Input ELEME {’HÉTFŐ’,’KEDD’,’SZERDA’…}
     Uf: Input=’HÉTFŐ’  Þ  x=Hetfo  ES  …}

  Procedure Ki(Const x:TNap);
    {Ef: –
     Uf: x.felsKod=Hetfo  Þ  Output=’HÉTFŐ’  ES  …}

  Function HibasE(Var x:TNap):Boolean;

 Implementation

  Type
   
TNapS=Array [1..7] of String[9];

  Const
    NapS:TNapS=(’HÉTFŐ’,’KEDD’,’SZERDA’,
                ’CSÜTÖRTÖK’,’PÉNTEK’,
                ’SZOMBAT’,’VASÁRNAP’);

  Procedure Min(Var minKi:TNap);
    {Ef: –
     Uf: minKi=TNap(Hetfo,Hamis)}
  Begin
    minKi.felsKod:=Hetfo; minKi.hiba:=False
  End;

 

  Function Szamossag:Word;
    {Ef: –
     Uf: Szamossag=7}

  Begin
    Szamossag:=7
  End;

  Procedure Kovetkezo(Var x:TNap; Var kovetkezoKi:TNap);
    {Ef: x.felsKod<>Vasarnap
     Uf: x.felsKod=Hetfo  Þ KovetkezoKi.felsKod=Kedd  ES…}
  Begin
    With
x do
    Begin
      {Ef-ellenőrzés:}
      If felsKod<>Vasarnap then
      Begin
      
 hiba:=True;
Exit
      End;
      {művelet-törzs:}
      KovetkezoKi.felsKod:=Succ(felsKod)
    End;
  End;

 

  Function HibasE(Var x:TNap):Boolean;

  Begin
    HibasE:=x.hiba; x.hiba:=False
  End;

Begin

End.

Megjegyzések:

Példa:

Program AProgram;
  Uses …,TNapUnit,….;
  Var
    tegnap,ma,holnap:TNap;
 

Begin
 

  Repeat
   
Write(’Milyen nap van ma?:’); Be(ma);
  Until not HibasE
(ma);

 
  Writeln(’Holnap:’);
  Kovetkezo(ma,holnap); Ki(holnap);
 

End.

Egy más elvű megoldást is találhatunk, ami azonban nem a modulból, hanem az exportmodul­ból indul ki. Ötlete a következő: a napok absztrakt felsorolását egészítsük ki egy további, pl. NemDef-fel elkeresztelt értékkel. Az előbbi TNapK és TNap kettőse helyett ábrázoljuk így:

Típus TNapK=(Hétfő, Kedd, Szerda, Csütörtök, Péntek,
             Szombat, Vasárnap, NemDef)

Változó érték:TNapK

Ekkor egyszerű értéktípusúak lesznek az eleddig rekord-típusú értéket szolgáltató függvé­nyek. Pl.:

Függvény Következő(Változó x:TNap):TNap
  Ef: x
¹Vasárnap
  Uf: x=Hétfő
 Þ Következő(x)=Kedd  Ù

  Ha érték=Vasárnap akkor   x:=NemDef
                   különben Következő:=Következő
[SzP3] (érték)
Függvény vége.

Így a Pascal-megfeleltetés úgyszólván problémamentes:

Unit TNapUnit;{InputParaméterek}

 Interface

   Type
     TNapK=(Hetfo,Kedd,Szerda,Csutortok,
            Pentek,Szombat,Vasarnap, NemDef);

    {a TNap=Record ertek:TNapK End helyett:}

     TNap=TNapK;

  
   Function
Kovetkezo(Var x:TNap):TNap;
   

 Implementation

    
    Function
Kovetkezo(Var x:TNap):TNap;
    {Ef: x<>Vasarnap
     Uf: x=Hetfo
 Þ Kovetkezo(x)=Kedd  ES …}
    Begin
      If x=Vasarnap then x:=NemDef
                    else Kovetkezo:=Succ(x)
    End;

  

2.2. Kódtöredék automatikus beillesztése

A unitok nyilvánvaló hátrányát igyekszik kiküszöbölni az „állomány automatikus beillesztés” lehetősége. A lényeg: a Pascal fordítóprogramot „rávesszük”, hogy a kódtöredéket tartalmazó file-t a befoglaló program adott pontján illessze be. Ennek módja: {$i töredék-file-név} direktíva az adott helyen.

Példa:

           Legyen az alábbi töredék a TNap.inc nevű file-ban:

{TNap
 
InputParaméterek – ha lennének. Most nincs.
}

  Type
    TNapK=(Hetfo,Kedd,Szerda,Csutortok,
           Pentek,Szombat,Vasarnap);
    TNap=Record felsKod:TNapK; hiba:Boolean End;
    TNapS=Array [1..7] of String[9];

  Const
    NapS:TNapS=(’HÉTFŐ’,’KEDD’,’SZERDA’,
                ’CSÜTÖRTÖK’,’PÉNTEK’,
                ’SZOMBAT’,’VASÁRNAP’);
 

  Procedure Kovetkezo(Var x:TNap; Var kovetkezoKi:TNap);
    {Ef: x.felsKod<>Vasarnap
     Uf: x.felsKod=Hetfo  Þ KovetkezoKi.felsKod=Kedd  ES…}
  Begin
    With
x do
    Begin
      {Ef-ellenőrzés:}
      If felsKod<>Vasarnap then
      Begin
      
 hiba:=True; Exit
      End;
      {művelet-törzs:}
      KovetkezoKi.felsKod:=Succ(felsKod)
    End;
  End;

 

           A felhasználás:

Program AProgram;
  Uses …;
 
  {$i TNap.inc – a TNap típus beillesztése}
  Var
    tegnap,ma,holnap:TNap;
 

Begin
 

End.

Megjegyzés:

2.3. Objektum-osztály

Objektum, helyesebben objektum-osztály fogalma számunkra azzal az előnnyel jár, hogy a programon belül megvalósíthatjuk a megfelelő típusfogalmat, azaz az értékhalmaz és műve­lethalmaz egységét, egységbezárását (encapsulation).[3] A szintaxisáról elegendő ennyit tudni:


  Type
   
TipusNev=Object
     

      {mező-deklarációk, amit itt az objektum
       attribútumainak vagy tulajdonságainak hívnak}
     
      {a típus műveleteinek, metódusainak fejsorai következnek:}
      Constructor EljC(…); {elhagyható}
      Destructor EljD(…); {elhagyható}
      Procedure Elj1(…);
      
      Function Fv1(…):TFv1;
     
    End;

    {a típus műveleteinek kifejtése:}
    Constructor TipusNev.EljC(…);
   
    Begin
     
    End;
    Destructor TipusNev.EljD(…);
   
    Begin
     
    End;
    Procedure TipusNev.Elj1(…);
    
    Begin
     
    End;

   
    Function TipusNev.Fv1(…):TFv1;
   
    Begin
     
    End;

 
  Var
    a,b,c:TipusNev;
 

Begin
 
  a.EljC(…); {az a objektum konstruktorának „hívása” a létrehozás kedvéért}
  a.Elj1(…); {az a objektum Elj1 műveletének „hívása”}
 

Megjegyzések:

Példa:

           Legyen a töredék az alábbi, ONap.inc nevű file-ban:

{Osztály ONap[4]

 
InputParaméterek – ha lennének. Most nincs ilyen.
}

  Type
    TNapK=(Hetfo,Kedd,Szerda,Csutortok,
           Pentek,Szombat,Vasarnap);
    TNapS=Array [1..7] of String[9];
  Const
    NapS:TNapS=(’HÉTFŐ’,’KEDD’,’SZERDA’,
                ’CSÜTÖRTÖK’,’PÉNTEK’,
                ’SZOMBAT’,’VASÁRNAP’);

  Type
    ONap=Object
      felsKod:TNapK;
      hiba:Boolean;
      Procedure Min(Var minKi:ONap);
      Procedure Max(Var maxKi:ONap);
      Function Szamossag:Word;
      Procedure Kovetkezo(Var x:ONapkovetkezoKi:ONap);
      Procedure Elozo(Var x:ONap)elozoKi:ONap);
      Function Sorszam(Const x:ONap):Word;
      Procedure ONap(Var x:Word):ONap;
      Procedure Be(Var x:Word);
      Procedure Ki(Const x:Word);
      Function HibasE(Var x:ONap):Boolean;

    End;
    Procedure ONap.Min(Var minKi:ONap);
      {Ef: –
       Uf: minKi=ONap(Hetfo,Hamis)}
    Begin
      minKi.felsKod:=Hetfo; minKi.hiba:=False
    End;

   

    Function ONap.Szamossag:Word;
      {Ef: –
       Uf: Szamossag=7}
    Begin
      Szamossag:=7
    End;

    Procedure ONap.Kovetkezo(Var kovetkezoKi:ONap);
      {Ef: felsKod<>Vasarnap
       Uf: felsKod=Hetfo  Þ KovetkezoKi.felsKod=Kedd  ES…}
    Begin
      {Ef-ellenőrzés:}
      If felsKod<>Vasarnap then
      Begin
      
 hiba:=True; Exit
      End;
      {művelet-törzs:}
      kovetkezoKi.felsKod:=Succ(felsKod)
    End;

 

           A felhasználás:

Program AProgram;
  Uses …;
 
  {$i ONap.inc – az ONap osztály beillesztése}
  Var
    tegnap,ma,holnap:ONap;
 

Begin
 

  Repeat
   
Write(’Milyen nap van ma?:’); ma.Be;
  Until not
ma.HibasE;
 
  Writeln(’Holnap:’); ma.Kovetkezo(holnap); holnap.Ki;
 

End.


 

Tartalom

ProgramozásMódszertan 2. előadás’2005 (vázlat) 1

1. A modul mint a típusmegvalósítás kerete. 1

1.1 Mi a típus?. 1

Amit már tudunk – „statikus kellékek”. 1

Miket kell megadni ahhoz, hogy mondhassuk: a típust „teljesen” ismerjük?. 1

Mit értünk a típus megvalósítása alatt?. 1

1.2. A típus algebrai specifikációjáról 1

1.3. A modul 4

2. A modulfogalom és a Pascal nyelv. 12

2.1. Unit 12

2.2. Kódtöredék automatikus beillesztése. 16

2.3. Objektum-osztály. 18

Tartalom.. 21

 



[1]  A konstansokat 0-változós függvényeknek tekintjük.

[2]  <:TNapxTNap→Logikai rendezés visszavezetése <:EgészxEgész→Logikai rendezésre.

[3]  Persze elismerjük, hogy ennél jóval több újdonságot rejt az objektumok fogalma, számunkra most ennyi pontosan elegendő.

[4] Az „O” a „T” helyett utalás, hogy „Objektum-Osztály”-ról van szó. Csak „helyi” konvenció!


 [SzP1] Lehetne így is:

Függvény Következő(Konstans x:TNap): TNap

És ha hiba történt, akkor e tényt a TNap típusú eredmény-adat árulja el, az ő hiba-flag-je Igaz. Ez azonban sok gondot vet föl. Pl. egy kifejezés eredményeként születik egy hibás TNap-konstants?!?

 [SzP2]Típus-konstrukciós függvény

 [SzP3]Ez a TNapK nem pedig az éppen definiálandó TNap Következő művelete.