Ogólne jednostki programowe 1
Przykład.
Procedura Wymien
W Adie parametry formalne i parametry aktualne
podprogramów muszą być zgodne.
Procedura wymieniająca wartości zmiennych typu
Natural
procedure
Wymien_Natural (N1, N2 :
in out
Natural)
is
Temp: Natural;
begin
Temp := N1;
N1 := N2;
N2 := Temp;
end
Wymien_Natural;
Ogólne jednostki programowe 2
Ta sama procedura wymieniająca wartości zmiennych
typu Float
procedure
Wymien_Float (F1, F2 :
in out
Float)
is
Temp: Float;
begin
Temp := N1;
N1 := N2;
N2 := Temp;
end
Wymien_Float;
Przy wymianie danych innych typów musimy pisać
nowe procedury i nigdy nie mamy pewności, że te
które już napisaliśmy wyczerpią wszystkie aktualne
i przyszłe potrzeby programów klienckich.
Ogólne jednostki programowe 3
Wszystkie procedury Wymien możemy umieścić w
pakiecie, np. Procedury_Wymiany, ale po
włączeniu do niego procedury obsługującej
kolejny typ danych, musimy dokonać ponownej
kompilacji tego pakietu.
Podejście takie jest
nieoszczędne, nieeleganckie i
zawodne
, bo w przypadku wykrycia i usunięciu
błędów w jednej z testowanych procedur możemy
zapomnieć o poprawie jednej, lub kilku
pozostałych.
Zadanie.
Czy procedury Wymien_Natural i
Wymien_Float mogą obydwie mieć nazwę Wymien?
Ogólne jednostki programowe 4
Ada umożliwia opracowanie jednej procedury
ogólnej
(
generic
), która po odpowiednim
przystosowaniu, nazywanym
konkretyzacją
(
instantation
) do aktualnie używanego typu
danych może być użyta w programie klienckim
wymieniającym wartości zmiennych.
Procedura ogólna wymieniająca wartości typu
Typ_Danych może mieć postać:
procedure
Wymien_Ogolnie (W1, W2 :
in out
Typ_Danych)
is
Temp: Typ_Danych;
begin
Temp := N1;
N1 := N2;
N2 := Temp;
end
Wymien_Ogolnie;
Ogólne jednostki programowe 5
Typy jako parametry formalne jednostki ogólnej
W tekście programu musimy umieścić sekcję ogólną,
w której deklarujemy nazwę typu będącego typem
parametrów procedury Wymien_Ogolnie,
podajemy nagłówek tej procedury, a potem całą jej
deklarację. Piszemy:
-- Specyfikacja ogólnej procedury wymiany
generic
type
Typ_Danych
is private
;
procedure
Wymien_Ogolnie (W1, W2 :
in out
Typ_Danych);
-- Treść ogólnej procedury wymiany
-- Tutaj wstawiamy treść pokazaną na poprzednim
-- slajdzie
Ogólne jednostki programowe 6
Kompilacja tej procedury daje kod gotowy do jej
konkretyzacji w programie klienckim, lub w
dalszej części naszego programu, w którym
pojawiła się sekcja ogólna.
W przypadku typów Integer i Natural
konkretyzacje mogą mieć postać:
procedure
Wymien_Integer
is new
Wymien_Ogolnie
(Typ_Danych => Integer);
procedure
Wymien_Float
is new
Wymien_Ogolnie
(Typ_Danych => Float);
Zadanie.
Czy typ Typ_Danych zadeklarowany w
sekcji ogólnej jako
private
, może być typem
prywatnym ograniczonym –
limited private
?
Uzasadnij odpowiedź.
Ogólne jednostki programowe 7
Przykład.
Program
Wymiana_Ogolna
W programie sekcja ogólna i treść procedury
ogólnej znajdują się w części deklaracyjnej
programu.
Drugim rozwiązaniem jest umieszczenie
procedury ogólnej w pakiecie, którego część
publiczna zawiera deklarację typu Typ_Danych i
nagłówek naszej procedury Wymien_Ogolnie
Przykład.
Pakiet
Wymiana
Program
Wymiana_Ogolna_Import
Ogólne jednostki programowe 8
Definicja.
Jednostka ogólna
(
generic unit
) jest
wzorcem
(
template
) procedury, funkcji, albo pakietu.
Jednostka ogólna definiowana jest z parametrami
formalnymi, którymi zazwyczaj są typy danych, ale
mogą nimi być też nazwy procedur i funkcji.
Podprogramy jako parametry formalne
jednostki ogólnej
Przykład.
Weźmy pod uwagę funkcję obliczającą wartość
większego z jej dwóch argumentów typu Integer.
Ogólne jednostki programowe 9
function
Maksimum (A, B :
in
Integer)
return
Integer
is
Wynik : Integer;
begin
if
A > B
then
Wynik := A;
else
Wynik := B;
end if
;
return
Wynik;
end
Maksimum;
Chcemy skonstruować ogólną funkcję Maksimum
wyznaczającą wartość większego z dwóch jej
argumentów, niezależnie od tego jakiego są
typu. Możemy oczywiście użyć ogólnego typu
parametrów formalnych, aby poinformować
kompilator, że konkretyzacja może dotyczyć
dowolnego typu.
Ogólne jednostki programowe 10
Nie jest to jednak w rozpatrywanym przypadku
informacja wystarczająca ponieważ
nie wszystkie
typy mogące konkretyzować naszą funkcję ogólną
mają zdefiniowaną wstępnie relację większości,
używaną w części operacyjnej tej funkcji.
Możemy oczywiście napisać odpowiednią funkcję
obliczającą wartość tej relacji w przypadku
podanego w konkretyzacji typu, ale kompilator
musi
posiadać informację, że ma tej funkcji użyć.
W sekcji ogólnej umieszcza się informację, że
taka funkcja istnieje.
Piszemy:
Ogólne jednostki programowe 11
Sekcja ogólna
generic
type
Typ_Danych
is private
;
with function
Wiekszy(L, R :
Typ_Danych)
return
Boolean;
function
Maksimum (W1, W2 : Typ_Danych)
return
Typ_Danych;
Ogólne jednostki programowe 12
Treść funkcji ogólnej
function
Maksimum (W1, W2 : Typ_danych)
return
Typ_danych
is
begin
if
Wiekszy(W1, W2)
then
return
W1;
else
return
W2;
end if
;
end
Maksimum;
Ogólne jednostki programowe 13
Konkretyzacja w przypadku typu standardowego
Float może mieć postać:
function
Maksimum_Float
is new
Maksimum
(Typ_Danych => Float, Wiekszy => ">");
Trzeba jednak pamiętać, że kompilator
nie może
sprawdzić
, czy przy konkretyzacji stosujemy
właściwą funkcję wyznaczającą wartość relacji
Wiekszy.
Moglibyśmy
również napisać
function
Maksimum_Float
is new
Maksimum
(Typ_Danych => Float, Wiekszy => "<");
Ogólne jednostki programowe 14
Przykład.
Program
Obliczanie_Maksimum