Wstęp do programowania 2 wykład 6 typy dostępu c.d Agata Półrola Wydział Matematyki UŁ 2005/2006 http://www.math.uni.lodz.pl/~polrola
Przykład wykorzystania typów dostępu zob. pakiet rodzajowy listapak (lista sortowana)
type box; type wsk_box is access box; type box is record dane: integer; nast: wsk_box; end record;
Deklaracja stałych Można deklarować stałe typu dostępu c: constant wsk_box := new box'(0,null); przy deklaracji konieczne jest nadanie wartości początkowej bycie stałą oznacza w tym przypadku, że wartość typu dostępu musi cały czas odwoływać się do tego samego obiektu wartość wskazywanego obiektu można zmienić
c: constant wsk_box := new box'(0,null); l:wsk_box:=new box'(1,null); c.all := l.all; --c:=l; -- niepoprawne
sposób obsługi stałych typu dostępu wyjaśnia również sposób przekazywania elementów typu dostępu jako parametrów podprogramów function suma(p: wsk_box) return integer is pom:wsk_box :=p; s: integer :=0; begin while pom /= null loop s := s + pom.dane; end loop; return s; end suma;
Przekazywanie parametrów podprogram operuje na kopii zmiennej będącej parametrem w przypadku parametru w trybie out jego wartość jest kopiowana do podprogramu, aby zapobiec losowym odwołaniom
Pool-specific access types Poznane dotychczas typy dostępu są typami pool-specific nowe obiekty są alokowane w obszarze pamięci (storage pool) skojarzonym z danym typem dostępu obszar skojarzony z typem dostępu przestaje istnieć gdy skończy się zasięg widoczności tego typu
obiekty do których odwołujemy się za pomocą pool specific access types muszą być obiektami zaalokowanymi za pomocą new b:box; w: wsk_box := b; -- niepoprawne Ograniczenie to nie występuje w przypadku tzw. ogólnych typów dostępu (general access types)
W przypadku gdy zaalokowany obiekt przestaje być dostępny (nie odwołuje się do niego żadna wartość typu dostępu) zajmowana przez niego pamięć może zostać automatycznie zwolniona (garbage collection). w praktyce jest to zaimplementowane w niewielu kompilatorach
w1: wsk_int_1 := new integer'(2); w2: wsk_int_2 := new integer'(4) w1.all := w2.all; -- w1 := w2; -- niedozwolone Nie ma możliwości konwersji jednego pool-specific access type na inny (nawet w pokazany wyżej sposób). Wartość typu dostępu może odwoływać się tylko do obiektów w swoim obszarze.
Sposoby inicjowania zmiennej a: array(1..10) of wsk_box := (1..10 => new box); -- alokacja 10 obiektów b1,b2: wsk_box := new box; -- alokacja 2 obiektów nn: wsk_box := new box'(1,null); ll: wsk_box := new box'(nn.all); i: integer := 2; nnn: wsk_int := new integer'(i);
Zakresy Typy dostępu mogą odwoływać się do: podtypów type wsk_pos is access positive; type wsk_pos1 is access integer range 1.. integer'last; wp : wsk_pos := new positive'(10); wp1 : wsk_pos := new integer'(10); wp2 : wsk_pos := new integer'(0); -- Constraint_Error
tablic zawężonych lub niezawężonych type tab is array (integer range <>,integer range <>) of float; type wsk_tab is access tab; wt,wt1 : wsk_tab; -- przy alokacji trzeba podać rozmiar: wt := new tab'(1..10 => (1..10 => 0.0)); wt1 := new tab(1..5,1..5); -- niedozwolone: wt1 := new tab; wt, wt1 mogą odwoływać się do tablic różnego rozmiaru po zaalokowaniu rozmiar tablicy nie może być zmieniany
subtype wsk_tab_3 is wsk_tab(1..3,1..3); wt3: wsk_tab_3; -- odpowiednik wt33 : wsk_tab(1..3,1..3); subtype tab3 is tab(1..3,1..3); wt3 := new tab3; wt33 := new tab3'(others=>(others=>0.0));
Odwołanie do elementów tablic: wt := new tab'(1..10 => (1..10 => 0.0)); wt1 := new tab(1..5,1..5); wt(1,1) := 0.1; wt.all := (others=> (others=> 0.1));
Typy dostępu mogą odwoływać się do innych typów dostępu type wsk_int is access integer; wi: wsk_int := new integer'(4); type wsk_wsk is access wsk_int; www: wsk_wsk; begin www:=new wsk_int; www.all := wi; put(www.all.all); www.all.all := 2;
General access types Dotychczas poznane typy dostępu umożliwiały operacje na elementach tworzonych dynamicznie (alokowanych za pomocą new) Typy dostępu mogą służyć do odwoływania się do obiektów zadeklarowanych statycznie. Są to tzw. ogólne typy dostępu (general access types).
type wsk_int_g is access all integer; i: aliased integer:=0; wii: wsk_int_g; wii:=i'access; można czytać i modyfikować wartość zmiennej i za pomocą zmiennej typu dostepu
w deklaracji typu dostępu używamy słowa all, zmienne do których odwołujemy się w powyższy sposób deklarujemy jako aliased ostrzeżenie dla programisty (zmienna może być modyfikowana niebezpośrednio) informacja dla kompilatora (nie należy przydzielać miejsca na zmienną w niestandardowy sposób uniemożliwiający późniejsze odwołanie)
Ograniczenie dostepu Możemy ograniczyć dostęp do zmiennej tak, aby zmienne (i stałe) były tylko do odczytu type wsk_int_c is access constant integer; i: aliased integer; ic: aliased constant integer := 1212; wii: wsk_int_c; wii:=i'access; -- dostep do zmiennej wii:=ic'access; -- dostep do stalej
Dostęp do elementów tablic składowe tablicy również mogą być zadeklarowane jako aliased tabi : array(1..100) of aliased integer; type wsk_int_g is access all integer; wii:= wsk_int_g; wii:= tabi(i)'access;
Dostęp do pól rekordu można również deklarować jako aliased pola rekordu type komorka is record i: aliased integer; j: integer; end record; type wsk_int_g is access all integer; wii:= wsk_int_g; k: komorka; wii:=k.i'access;
Konwersja typów konwersja dla pool-specific access types nie jest dozwolona konwersja między general access type jest możliwa: wskazywane typy muszą być takie same zakresy podtypów muszą być zgodne typ dostępu tylko do odczytu nie może być przekonwertowany na typ dostępu do zmiennej
pool-specific type może być przekonwertowany do general access type, ale nie odwrotnie