APP 15 Typy Pochodne

background image

Typy pochodne 1

Wstęp

Często dogodnie jest wprowadzić nowy typ, który

jest podobny do istniejącego, niemniej jednak

różny

.

Niech T będzie pewnym typem. Możemy napisać:

type S is new T;

W takim przypadku mówimy, że S jest

typem

pochodnym

(

derived type

) typu T, który

nazywamy

typem macierzystym

(

parent type

).

Mówimy czasami, że S należy do tej samej

klasy

co typ T.

background image

Typy pochodne 2

Jeżeli T jest typem rekordowym, to typ S jest też

typem rekordowym, a jego składowe mają te
same identyfikatory.

Zbiór wartości typu pochodnego

jest kopią

zbioru

wartości typu macierzystego. Oznacza to, że

to różne typy

i

nie można

wartości jednego

typu podstawiać do obiektów drugiego typu.
Konwersja jest jednak możliwa.

Zapis literałów i agregatów typu pochodnego jest

taki taki sam, oraz domyślne wyrażenia
początkowe typu, albo jego składowych są takie
same jak w przypadku typu macierzystego.

background image

Typy pochodne 3

Operacje podstawowe

Definicja. Do

operacji podstawowych

typu

zaliczamy:

1. Zdefiniowane wstępnie operacje podstawienia,

zdefiniowana wstępnie relacja równości,

odpowiednie atrybuty.

2. W przypadku typu pochodnego, operacjami

podstawowymi są operacje podstawowe

odziedziczone po typie macierzystym, które

mogą być ponownie zdefiniowane.

3. W przypadku typu zadeklarowanego w pakiecie

definicyjnym, podprogramy zadeklarowane w

tym pakiecie, posiadające parametry formalne,

lub wynik tego typu.

background image

Typy pochodne 4

W

artości typu wyliczeniowego są także operacjami

podstawowymi, ponieważ są traktowane jak
identyfikatory funkcji bezparametrowych o
wartościach typu wyliczeniowego.

Przykład.

W przypadku typu Boolean, literały False

i True są operacjami podstawowymi, ponieważ są
traktowane jakby były funkcjami, takimi jak:
function True return Boolean is
begin
return Boolean’Val(1);
end;

background image

Typy pochodne 5

Ogólna idea jest taka, że typ pochodny posiada pewne

operacje podstawowe, dziedziczone po typie

macierzystym i można do zbioru tych operacji dodać

nowe operacje podstawowe.

Przykład.

Pakiet definicyjny Wektory_Na_Plaszczyznie.
Program Test_Wektory_Na_Plaszczyznie.

Operacje dziedziczone

mogą być zastąpione

przez nowe

operacje.

Rozumiemy przez to zastąpienie operacji dziedziczonych

przez

jawnie

zadeklarowane podprogramy o tych

samych identyfikatorach jak podprogramy należące do

zbioru operacji podstawowych typu macierzystego,

przy czym podprogramy zastępujące

muszą być

zadeklarowane w tym samym obszarze deklaracji, w

którym definiowany jest typ pochodny.

background image

Typy pochodne 6

Deklarując typ pochodny

należy

przestrzegać dwóch

zasad:

1.

Nie można tworzyć typu pochodnego z typu

prywatnego przed podaniem pełnej deklaracji tego

typu.

2.

Jeżeli tworzymy typ pochodny w tym samym pakiecie

definicyjnym, w którym deklarujemy typ macierzysty,

to typ pochodny dziedziczy wszystkie operacje po typie

macierzystym i nie można dodać nowych operacji do

typu macierzystego po deklaracji typu pochodnego.

Mimo że, każdy typ pochodny jest różny, to dzięki

pokrewieństwu typów pochodnych, wyprowadzonych

od wspólnego przodka, wartość jednego typu

pochodnego można łatwo zamienić na wartość innego

typu powstałej klasy.

background image

Typy pochodne 7

Przykład.

Niech będą dane deklaracje:

type Light is new Colour;
type Signal is new Colour;
type Flare is new Signal;

Typy te tworzą hierarchię typów, która zaczyna się

od typu Colour. Możemy swobodnie dokonywać
konwersji wartości tych typów. Na przykład
możemy pisać:
L : Light;
F : Flare;
...
F := Flare(L);

zamiast

F := Flare(Signal(Colour(L)));

background image

Typy pochodne 8

Podstawową zaletą

wprowadzania typów

pochodnych jest unikanie mieszania obiektów,

koncepcyjnie należących do różnych typów.

Przykład.

Załóżmy, że chcemy liczyć jabłka i pomarańcze.

W tym celu możemy napisać
type Apples is new Integer;
type Oranges is new Integer;
...
No_Of_Apples : Apples;
No_Of_Oranges : Oranges;

Obydwa typy pochodzą od typu Integer, dzięki czemu

obydwa dziedziczą operację dodawania, co pozwala pisać
No_Of_Apples := No_Of_Apples + 1;
No_Of_Oranges := No_Of_Oranges + 1;

background image

Typy pochodne 9

Nie wolno oczywiście pisać:

No_Of_Apples := No_Of_Oranges;

ale zamiast tego trzeba użyć konwersji

No_Of_Apples := Apples'(No_Of_Oranges);

Przypuśćmy, że dwie procedury obsługują sprzedaż obydwu

rodzajów owoców

procedure Sell (N : Apples);

procedure Sell (N : Oranges);

Możemy wywołać jedną z nich

Sell (N : No_Of_Oranges);

natomiast wywołanie

Sell (6);

jest niejednoznaczne i w celu usunięcia tej niejednoznaczności

trzeba pisać
Sell (Oranges'(6));

background image

Typy pochodne 10

Jeżeli podprogram jest dziedziczony, to w

rzeczywistości

nie jest tworzony nowy

podprogram

.

Wywołanie podprogramu dziedziczonego jest

wywołaniem podprogramu macierzystego, przy
czym parametry rodzajów in i in out są niejawnie
konwertowane na typ macierzysty tuż

przed

wywołaniem, a parametry rodzajów in out i out
konwertowane niejawnie zaraz

po

wywołaniu

podprogramu.

Pisząc

My_Apples + Your_Apples

mamy

Apples(Integer(My_Apples) + Integer(Your_Apples))

background image

Typy pochodne 11

Zajmijmy się teraz ograniczeniami. Możemy tworzyć typy

pochodne ograniczone.

Przykład.

type Probability is new Float range 0.0..1.0;

Jest to równoważne dwóm deklaracjom:

type Anonim is new Float;
subtype Probability is Anonim range 0.0..1.0;

Oznacza to, że podtyp Probability jest podtypem

ograniczonym anonimowego typu pochodnego. Zauważmy,
że zbiór wartości typu pochodnego jest kopią zbioru
wartości typu macierzystego Float. Operacje "+" , ">" i
inne, działają w całym nieograniczonym zbiorze wartości.

background image

Typy pochodne 12

Przykład.

Niech

P : Probability;

Można napisać

P > 2.0

Mimo, że

nie można

podstawić wartości 2.0 do zmiennej P.

Podane wyrażenie jest zawsze nieprawdziwe, chyba że

zmienna P nie jest zainicjowana odpowiednio i przez

przypadek ma złą wartość.

Rozpatrzmy teraz ograniczenia występujące w przypadku

dziedziczonych podprogramów.

Podprogram odziedziczony

jest podprogramem macierzystym

w którym wszystkie egzemplarze (

instances

) typu

macierzystego

są wymienione

na typ pochodny.

Podtypy są wymienione na równoważne podtypy z odpowiednimi

ograniczeniami, a domyślne wyrażenia inicjujące są

konwertowane przez dodanie konwersji typów.

Dowolny parametr, albo wynik innego typu pozostaje

niezmieniony.

background image

Typy pochodne 13

Przykład.

Niech

type T is ...;
subtype S is T range L..R;
function F (X : T; Y : T := E; Z : Q) return S;

Przy czym E jest wyrażeniem inicjującym typu T, natomiast typ

Q nie należy do klasy T, a więc jest typem całkowicie

niezwiązanym.

Jeżeli napiszemy

type TT is new T;

to z tego wynika, że napisaliśmy też

subtype SS is TT range TT(L)..TT(P);

a nagłówek dziedziczonej funkcji F ma postać

function F (X : TT; Y : TT := TT(E); Z : Q)
return SS;

background image

Typy pochodne 14

W nagłówku typ T został zastąpiony

przez

TT, podtyp S

przez

SS,

dokonana została

konwersja wyrażenia

E na wartość typu TT,

natomiast typ Q

został niezmieniony

. Warto zauważyć, że

identyfikatory parametrów formalnych

zostały takie same

.

Typy pochodne są pewną alternatywą do typów prywatnych. Typy

pochodne

mają zaletę

dziedziczenia literałów, ale często

mają wadę

dziedziczenia zbyt wielu rzeczy po typie

macierzystym.

Przykład.

Weźmy pod uwagę deklaracje

type Length is new Float;
type Area is new Float;

Wprowadzenie tych typów zabezpiecza przed mieszaniem

długości i powierzchni, ale dziedziczona jest możliwość

mnożenia dwóch egzemplarzy typu Length, w wyniku czego

dostaniemy wartość typu Length. Poza tym, dziedziczymy

wiele nieistotnych operacji jak np. potęgowanie.

background image

Typy pochodne 15

Takie niepożądane operacje można, jeżeli trzeba, zastąpić

podprogramami abstrakcyjnymi

, takimi jak:

function "*" (Left, Right : Length) return

Length

is abstract;

Podprogram abstrakcyjny

nie ma treści

i

nie można go

wywołać

. Każda próba wywołania wykrywana jest jako błąd

podczas kompilacji.

Zalecenie

. Jeżeli jest wiele niepożądanych operacji

dziedziczonych po typie macierzystym, często lepiej użyć
typu prywatnego i zdefiniować te operacje których
potrzebujemy.

Zadanie

. Zadeklarować pakiet Metrics zawierający deklaracje

typów pochodnych Length i Area wraz z odpowiednimi
nagłówkami różnych operacji "*", "/", "**".


Document Outline


Wyszukiwarka

Podobne podstrony:
APP 12 Typy Wskaznikowe Ogolne
APP abstrakcyjne Typy Danych
APP 04 Typy Standardowe 2010
APP 02 Typy Danych Podstawy 2010
APP 14 Typy Prywatne 2010
15 TYPY I RODZ SP, szkoła
04.Typy (2) , TYPY POCHODNE
app 15
15 Pochodne kwasów karboksylowych (08 11 2011)
ZPI 2014-15, ZPI folie 6, Instrumenty pochodne w zarządzaniu portfelem inwestycyjnym
Pochodzenie i typy użytkowe trzody chlewnej
Pajewski, Meandry sporów o pochodzenie 15 (PG 2007)
15 Pochodne kwasow karboksylowych materiały dodatkowe
15 Pochodne kwasów karboksylowych (08 11 2011)
2 Pochodna calkaid 21156 ppt

więcej podobnych podstron