background image

Antoni M. Zaj czkowski: Algorytmy i podstawy programowania  – ogólne jednostki programowe 

25 maja 2009

 

 

O

GÓLNE JEDNOSTKI PROGRAMOWE

 

Pami tamy,  e w Adzie typy parametrów formalnych i aktualnych funkcji i procedur musz  

by  zgodne. Oznacza to,  e podprogram realizuj cy ten sam algorytm dla dwóch ró nych ty-

pów danych musi by  napisany dwukrotnie – dla ka dego z typów osobno. 

Przykład.

 (

Feldman, Koffman, 1996

). 

We my pod uwag  nast puj c  procedur : 

procedure

 Exchange (Element_1, Element_2 : 

in out

 Natural) 

is 

  Temp : Natural; 

begin 

  Temp := Element_1; 
  Element_1 := Element_2; 
  Element_2 := Temp; 

end

 Exchange; 

Procedura ta wymienia warto ci dwóch zmiennych typu Natural. Je eli chcemy wymieni  
wielko ci typu Float, to musimy napisa  drug  procedur : 

procedure

 Exchange (Element_1, Element_2 : 

in out

 Float) 

is 

  Temp : Float; 

begin 

  Temp := Element_1; 
  Element_1 := Element_2; 
  Element_2 := Temp; 

end

 Exchange; 

Zauwa my,  e procedury te s  identyczne z wyj tkiem typów danych na jakich wykonywane 

s  te same instrukcje. W przypadku, gdy chcemy wymieni  warto ci zmiennych innego typu 
mo emy napisa  kolejn  procedur  Exchange itd. Wszystkie procedury wymiany mo emy 

zamkn  w pewnym pakiecie bibliotecznym, ale nie jest to eleganckie i niezawodne rozwi -

zanie. W sytuacji, gdy program kliencki importuje jedn  z procedur wymiany z tego pakietu i 

oka e si ,  e procedura ta ma bł d, powinni my sprawdzi  czy inne procedury tego pakietu s  

poprawne. Lepiej napisa  jedn  

procedur  ogóln  (

generic

) wymieniaj c  warto ci pewnego 

typu  Element_Type,  który  ma  tylko  nazw   i  nie  ma  konkretnej  reprezentacji.  W  tym 

rozwi zaniu procedura mo e mie  posta : 

procedure

 Generic_Exchange (Element_1, Element_2 : 

in out

 Element_Type) 

  

is 

  Temp : Element_Type; 

begin 

  Temp := Element_1; 
  Element_1 := Element_2; 
  Element_2 := Temp; 

end

 Generic_Exchange; 

Oczywi cie, procedura ta mo e nazywa  si  jak poprzednie procedury, natomiast nazwa u yta 
tutaj podkre la fakt,  e procedura Generic_Exchange jest przepisem, recept , albo 

wzor-

cem  (

template

),  a  nie  procedur   gotow   do  wymiany  dwóch  elementów  dowolnego  typu. 

Klient procedury ogólnej musi j  przystosowa , czyli dokona  

konkretyzacji (

instantiation

do u ywanego przez niego typu danych. 
1.  Typy jako parametry formalne jednostki ogólnej 
Kompilator musi mie  informacje,  e procedura Generic_Exchange jest wzorcem, który 

dopiero po konkretyzacji mo e wymienia  warto ci konkretnego typu. W celu powiadomienia 

kompilatora  o  tym,  e  procedura  ta  jest  procedur   ogóln   w  tre ci  programu  umieszczamy 

sekcj   ogóln ,  w  której  podajemy  nazw   typu  b d cego  typem  parametrów  tej  procedury 

oraz podajemy jej nagłówek, a nast pnie cał  jej deklaracj . Mo emy wi c napisa  

-- Specification of the generic exchange procedure  

background image

Antoni M. Zaj czkowski: Algorytmy i podstawy programowania  – ogólne jednostki programowe 

25 maja 2009

 

 

generic 

  

type

 Element_Type 

is private

  

procedure

 Generic_Exchange  

   (Element_1, Element_2 : 

in out

 Element_Type); 

  

procedure

 Generic_Exchange (Element_1, Element_2 : 

in out

 Element_Type) 

    

is 

    Temp : Element_Type; 

  begin 

    Temp := Element_1; 
    Element_1 := Element_2; 
    Element_2 := Temp; 

  end

 Generic_Exchange; 

Kompilacja sekcji ogólnej generuje kod gotowy do jej konkretyzacji w programie klienckim, 

lub w dalszej cz ci naszego programu, w którym istnieje taka sekcja. 
W przypadku typów Natural i Float odpowiednie konkretyzacje mog  mie  posta  

procedure

 Exchange_Natural 

is new

 Generic_Exchange 

  (Element_Type => Natural); 

procedure

 Exchange_Float 

is new

 Generic_Exchange 

  (Element_Type => Float); 

W programie sekcja ogólna i tre  procedury ogólnej znajduj  si  w cz ci deklaracyjnej pro-

gramu przed deklaracjami innych podprogramów. 
Drugim, bardziej uniwersalnym rozwi zaniem jest umieszczenie procedury ogólnej w pakie-
cie, którego cz

 publiczna zawiera identyfikator typu Element_Type i nagłówek proce-

dury. 

Program.

 Test_Generic_Exchange_Program. 

Pakiety.

 Exchange.ads, Exchange.adb. 

Program.

 Test_Generic_Exchange_Client. 

Zadanie.

 Czy typ prywatny Element_Type zadeklarowany w sekcji ogólnej jako prywatny  

(

private

) mo e by  typem prywatnym ograniczonym (

limited private

)? Uzasadnij 

odpowied . 
Mo emy teraz poda  definicj  jednostki ogólnej. 
D

EFINICJA

. Jednostka ogólna (

generic unit

) jest wzorcem podprogramu, albo pakietu. Jed-

nostka  ta  deklarowana jest  z  parametrami  formalnymi,  którymi  mog  by  typy  danych, lub 

identyfikatory podprogramów. 
2.  Podprogramy jako parametry formalne jednostki ogólnej 
We my  pod  uwag   funkcj   obliczaj c   warto   wi kszego  z  dwóch  jej  argumentów  typu 
Integer

function

 Maximum (A, B : Integer) 

return

 Integer 

is

 

  Result : Integer; 

begin 

  

if

 A > B 

then

 

    Result := A; 
  

else 

    Result := B; 
  

end if

end

 Maximum; 

Chcemy napisa  funkcj  ogóln  obliczaj c  warto  wi kszego z dwóch jej argumentów, nie-

zale nie od tego jakiego s  typu. Mo emy oczywi cie u y  ogólnego typu parametrów for-

malnych, aby poinformowa  kompilator o tym,  e konkretyzacja mo e dotyczy  dowolnego 

typu. Nie jest to jednak informacja wystarczaj ca, poniewa  nie wszystkie typy, które mog  
konkretyzowa  nasz  funkcj  Maximum, maj  zdefiniowan  wst pnie relacj  wi kszo ci wy-

background image

Antoni M. Zaj czkowski: Algorytmy i podstawy programowania  – ogólne jednostki programowe 

25 maja 2009

 

 

korzystywan  w cz ci operacyjnej tej funkcji. Mo emy napisa  funkcj  implementuj c  po-

trzebn  relacj  w przypadku konkretnego typu, ale kompilator musi mie  informacj ,  e ma t  

funkcj   zastosowa .  W  tym  celu  w  sekcji  ogólnej  umieszcza  si   informacj ,  e  potrzebna 

funkcja istnieje. W zwi zku z tym, piszemy: 

generic 

  

type

 Element_Type 

is private

  

with

 

function

 Greater(L, R : Element_Type) 

return

 Boolean; 

  

function

 Maximum (A, B : Element_Type) 

return

 Element_Type; 

  

function

 Maximum (A, B : Element_Type) 

return

 Element_Type 

is

 

    Result : Element_Type; 
  

begin 

    

if

 Greater(A, B) 

then

 

      Result := A; 
    

else

 

      Result := B; 
    

end if

  

end

 Maximum; 

Konkretyzacja tej funkcji w przypadku typu standardowego Float mo e mie  posta  

function

 Maximum_Float 

is new

  

  Maximum (Element_Type => Float, Greater => ">"); 

Program.

 Compute_Maximum. 

Zajmijmy si  teraz nieco trudniejszym zagadnieniem. Chcemy napisa  program, który znaj-

duje element ekstremalny w tablicy jednowymiarowej, przy czym indeksy tablicy mog  by  

dowolnego typu dyskretnego, a elementy s  dowolnego typu nieograniczonego (nie s  typu 

limited private

). W tym celu tworzymy sekcj  ogóln  

generic 

  

type

 Element_Type 

is private

-- Any unlimited type

 

  

type

 Index_Type 

is

 (<>); 

-- Any discrete type 

  

type

 Array_Type 

is array

 (Index_Type 

range

 <>) 

of

 Element_Type; 

  

with

 

function

 Order_Relation(L, R : Element_Type) 

return

 Boolean; 

Szukanie  elementu  ekstremalnego  wymaga  porównywania  elementów  tablicy  i  dlatego 

musimy  powiadomi   kompilator  o  tym,  e  b dzie  stosowana  odpowiednia  funkcja,  która 

obliczy relacj  dwóch elementów. 
Musimy jeszcze poda  nagłówek funkcji wyznaczaj cej element ekstremalny. Mo e on mie  

nast puj c  form : 

function

 Array_Extremum (List : Array_Type) 

return

 Element_Type; 

Sekcja  ogólna  zawiera  ju   wszystko  czego  potrzeba.  Teraz  trzeba  zadeklarowa   funkcj  

implementuj c  algorytm poszukiwania elementu ekstremalnego. 

function

 Array_Extremum (List : Array_Type) 

return

 Element_Type 

is

 

  Result : Element_Type := List(List’First); 

begin 

  

for

 I 

in

 List’

range

 

loop

 

    

if

 Order_Relation(List(I), Result) 

then

 

      Result := List(I); 
    

end if

  

end loop

  

retutn

 Result; 

end

 Array_Extremum; 

Zadanie.

 Dlaczego typ Element_Type nie mo e by  typem ograniczonym? 

W celu sprawdzenia, czy nasz algorytm poprawnie działa w ró nych sytuacjach deklarujemy 

nast puj ce typy: 

type

 Real_Vector 

is array

(Integer 

range

 <>) 

of

 Float; 

subtype

 Large_Letter 

is

 Character 

range

 'A'..'Z'; 

background image

Antoni M. Zaj czkowski: Algorytmy i podstawy programowania  – ogólne jednostki programowe 

25 maja 2009

 

 

type

 Large_Letter_Vector 

is array

 (Positive 

range

 <>) 

of

 Large_Letter; 

Zauwa my,  e  typy  tablicowe  okre laj   tablice  otwarte  o  konkretnych  typach  indeksów. 

Podobnie, konkretne s  typy elementów tablic, które s  typami standardowymi dzi ki czemu 

nie musimy pisa  własnych funkcji do porównywania egzemplarzy tych typów. 
Pozostała nam jeszcze konkretyzacja funkcji znajduj cej ekstrema. Mo emy napisa : 

function

 Array_Extremum_Float 

is new

 Array_Extremum 

  

(Index_Type => Integer, Element_Type => Float,  

   Array_Type => Real_Vector, Order_Relation => ">="); 

function

 Array_Extremum_Large_Letter 

is new

 Array_Extremum 

  

(Index_Type => Positive, Element_Type => Large_Letter,  

   Array_Type => Large_Letter_Vector, Order_Relation => "<="); 

Program.

 Generic_Array_Extremum