Object Pascal/Typy zmiennych
Typy zmiennych określają zewnętrzną postać zmiennej, czyli zakres jej wartości i zestaw dozwolonych operacji, które może na niej wykonać programista, a także jej reprezentację wewnętrzną, czyli sposób traktowania je przez inne obiekty programu.
Typ prosty
[edytuj]Porządkowy
[edytuj]Całkowity
[edytuj]Typ predefiniowany.
Typy ogólne
[edytuj]Nazwa typu | Zakres | Format |
---|---|---|
Integer | typ zależny od typu programowania, najczęściej od -32768 do 32767 | ze znakiem, 16 lub 32 lub 64 bitowy (w zależności od platformy na którą programujemy) |
Cardinal | typ zależny od typu programowania, najczęściej 0..4294967295 | bez znaku, 16 lub 32 lub 64 bitowy (w zależności od platformy na którą programujemy) |
Typy podstawowe
[edytuj]Nazwa typu | Zakres | Format |
---|---|---|
ShortInt | –128..127 | ze znakiem, 8-bitowy |
SmallInt | –32768..32767 | ze znakiem, 16-bitowy |
LongInt | –2147483648..2147453647 | ze znakiem, 32-bitowy |
Int64 | –2^64..2^64–1 | ze znakiem, 64-bitowy |
Byte | 0..255 | bez znaku, 8-bitowy |
Word | 0..65535 | bez znaku, 16-bitowy |
LongWord | 0..42849567295 | bez znaku, 32-bitowy |
QWord | 0 .. 18446744073709551615 | bez znaku, 64-bitowy |
Dodatkowe informacje
[edytuj]Predefiniowane w module System stałe MaxLongint i MaxInt określają maksymalną wartość w typach LongInt i Integer.
Logiczny
[edytuj]Typ predefiniowany.
Nazwa typu | Format |
---|---|
Boolean | 8 - bitowy |
ByteBool | 8 - bitowy |
WordBool | 16 - bitowy |
LongBool | 32 - bitowy |
Wartością zmiennej typu logicznego może być predefiniowana stała FALSE lub TRUE.
Znakowy
[edytuj]Typ predefiniowany.
Typy podstawowe
[edytuj]Nazwa typu | Format | Uwagi |
---|---|---|
AnsiChar | 8 - bitowy | rozszerzony zestaw znaków ASCII (standard 7 bitów) |
WideChar | 16 - bitowy | zestaw znaków Unicode |
Typ ogólny
[edytuj]Nazwa typu | Format | Uwagi |
---|---|---|
Char | 8 - bitowy | zgodny z typem AnsiChar w Object Pascal |
Wyliczeniowy
[edytuj]Typ niepredefiniowany, wymaga opisu programisty.
Definicja typu
[edytuj]type identyfikator-typu = (lista identyfikatorów)
Przykład
[edytuj]type samochody = (fiat, polonez, opel, volkswagen); //Ord(fiat) = 0 //Ord(polonez) = 1 itd. var x,y:samochody; begin x:=polonez; //x – 00000001 (liczba 1) y:=opel; //y – 00000010 (liczba 2) end;
Uwagi dotyczące stosowania typów wyliczeniowych
[edytuj]- Element tego typu zajmuje 8 lub 16 bitów.
- Identyfikatory na liście muszą być różne, błędna jest na przykład deklaracja
type znaki = (a,b,b,c)
- W dwóch różnych typach o tym samym zasięgu nie może wystąpić ten sam identyfikator, np. w zasięgu deklaracji typu samochody błędna jest deklaracja
type ciezarowki = (opel, volkswagen, scania)
- Porządek w typie wyliczeniowym jest zgodny z kolejnością wyliczenia w definicji typu.
- Wartości zmiennych tego typu nie można wypisać standardową procedurą write.
- Nie można na nich wykonywać operacji arytmetycznych.
- Maksymalna ilość elementów to 256.
Okrojony
[edytuj]Typ niepredefiniowany, wymaga opisu programisty. Służy do definiowania podzbiorów dowolnego zbioru wartości określonego przez typy porządkowe.
Definicja
[edytuj]type identyfikator-typu = stala1 .. stala2;
Z każdym typem okrojonym związany jest bazowy, macierzysty typ porządkowy i obie stałe muszą być tego typu, przy czym ord(stala1) <= ord(stala2). Pierwsze wyrażenie stałe nie może zaczynać się od ‘(‘.
Przykład
[edytuj]const a = 5; b = 2; type sam = fiat .. opel; // typ bazowy samochody znaki = '!' .. '+'; // typ bazowy Char zakres1 = 2+5 .. 2*5; // typ bazowy Byte zakres2 = b+a .. b*a; // typ bazowy Integer
Rzeczywisty
[edytuj]Typ predefiniowany. W odróżnieniu od typów całkowitych pozwala na operacje zmiennoprzecinkowe.
Typy podstawowe
[edytuj]Nazwa typu | Zakres | Znaczące cyfry | Format |
---|---|---|---|
Real48 | 2.9 x 10^–39 .. 1.7 x 10^38 | 11–12 | 48-bitowy |
Single | 1.5 x 10^–45 .. 3.4 x 10^38 | 7–8 | 32-bitowy |
Double | 1.5 x 10^–309 .. 1.7 x 10^309 | 15–16 | 64-bitowy |
Extended | 3.6 x 10^–4951 .. 1.1 x 10^4932 | 19–20 | 80-bitowy |
Comp | –2^63 .. 2^63 –1 | 19–20 | 64-bitowy |
Currency | –922337203685477.5808 .. 922337203685477.5807 | 19–20 | 64-bitowy |
Typ ogólny
[edytuj]Nazwa typu | Zakres | Znaczące cyfry | Format |
---|---|---|---|
Real | 5.0 x 10^–324 .. 1.7 x 10^308 | 15–16 | 64-bitowy |
Dodatkowe informacje
[edytuj]- Typ Extended zapewnia najlepszą precyzję, nie jest jednak zalecany, gdy aplikacja ma być uruchamiana na różnych platformach.
- Typ Comp służy do pamiętania dużych liczb całkowitych, nie jest jednak typem porządkowym (nie można go np. inkrementować), zachowany dla zgodności z wersjami wcześniejszymi, zaleca się używać typu Int64.
- Typ Currency ma zastosowanie do obliczeń pieniężnych.
Typ łańcuchowy
[edytuj]Typ łańcuchowy służy do reprezentowania ciągów znaków.
Łańcuchowy krótki
[edytuj]- string - w zasięgu takiej dyrektywy {$H-},
- string[zakres] - zakres mniejszy lub równy od 255,
- shortstring
Łańcuchowy długi
[edytuj]- string - w zasięgu dyrektywy {$H+} (ustawienie standardowe)
- ansistring;
Łańcuch znaków dwubajtowych
[edytuj]- widestring
Typ strukturalny
[edytuj]Tablicowy
[edytuj]Typ przeznaczony do struktur składających się z wielu elementów konkretnego typu.
Tablice statyczne
[edytuj]Deklaracja typu tablicowego:
type identyfikator_typu = array [typy_indeksowe] of typ_bazowy;
gdzie:
- typy_indeksowe – oddzielone przecinkami opisy typów porządkowych;
- typ_bazowy – dowolny typ prosty lub strukturalny.
Przykłady:
type Kolor = (bialy, zielony, czarny); Ttab1 = array [5..8] of array [Boolean] of array [Kolor] of real; Ttab2 = array [5..8, Boolean] of array [Kolor] of real; Ttab3 = array [5..8] of array [Boolean, Kolor] of real;
Deklaracja zmiennej w typie tablicowym:
var liczba: array [1..100] of integer;
W nawiasach kwadratowych zapisywany jest zakres indeksów tablicy w postaci: od..do. Indeks tablicy musi należeć do typu porządkowego, ograniczenia (od i do) nie mogą być zmiennymi. Ograniczeniom nie podlega zakres indeksów (jedyny warunek to indeks od musi być mniejszy od indeksu do. Typ_bazowy może być typem prostym, ale także typu strukturalnego.
Istnieją również tablice wielowymiarowe, np. dwuwymiarowa:
var liczba: array[1..10] of array[1..10] of integer;
albo dla skrócenia zapisu:
var liczba: array[1..10,1..10] of integer;
Nie ma ograniczeń na liczbę wymiarów tablicy, najczęściej stosuje się tablice jedno- i dwuwymiarowe.
Tablice dynamiczne
[edytuj]Deklaracja:
type identyfikator_typu = array of typ_bazowy; //tablica jednowymiarowa type identyfikator_typu = array of array of typ_bazowy //tablica 2-wymiarowa
Informacje:
- Zmienne tego typu zajmują 32 bity pamięci.
- Pamięć na tablicę alokowana jest w wyniku wykonania procedury SetLength (zmienna, indeksy) lub w wyniku przypisania.
- Pamięć jest zwalniana w wyniku przypisania zmienna := nil; lub w wyniku wykonania procedury Finalize (zmienna).
Rekordowy
[edytuj]Typem rekordowym nazywamy złożoną strukturę danych, której elementy (pola), mogą być różnych typów (prostych i strukturalnych).
Deklaracja typu rekordowego
[edytuj]type identyfikator_typu = record {lista_deklaracji_pól}; end;
gdzie lista_deklaracji_pól ma postać:
lista_identyfikatorów_pól : opis-typu;
Ważne informacje
[edytuj]- Ostatnie pole może być polem wariantowym postaci:
case pole_wyróżnikowe of wykaz_wariantów;
- Pole_wyróżnikowe może być identyfikatorem typu porządkowego lub deklaracją zmiennej porządkowej.
- wykaz_wariantów ma postać:
lista-etykiet-wyboru : (lista-deklaracji-pól)
- Pola muszą mieć różne identyfikatory.
- Żadne pole wariantowe nie może być:
- typu łańcuchowego długiego,
- typu tablicy dynamicznej,
- typu wariantowego,
- typu łącza programowego.
Przykład:
[edytuj]type Data = record Dzien: 1..31; Miesiac: 1..12; Rok: integer; end;
Zbiorowy
[edytuj]Typ zbiorowy jest zbiorem potęgowym typu porządkowego o maksymalnie 256 elementach.
Deklaracja typu
[edytuj]type identyfikator_typu = set of typ_porządkowy;
Wartościami zmiennych typu zbiorowego są dowolne podzbiory zbioru bazowego, łącznie ze zbiorem pustym. Konstruktor zbioru ma postać [ ].
Przykłady:
[edytuj]type Samochody = (fiat, polonez, opel, volkswagen); var A : set of samochody; B : set of 0..3; C : set of 'a'..'z'; begin A:= [ ]; A:= [opel]; B:= [1,3]; C:= ['a'..'f']; end.
Na zmiennych zbiorowych można wykonywać:
- operacje mnogościowe,
- operacje porównań,
- operację należenia do zbioru in,
- procedury:
include(zb, el) zb:=zb+[el] exclude(zb, el) zb:=zb-[el]
Plikowy
[edytuj]Klasowy
[edytuj]Typ klasowy jest podobny do typu rekordowego, posiada jednak dodatkowo metody (procedury i funkcje). Słowo class, oznacza taką strukturę, która posiada konstruktory (słowo kluczowe constructor) i destruktor (destructor), deklarowane podobnie jak inne metody. Zwyczajowo konstruktory są nazywane Create a destruktory Destroy. Konstruktora używa się do przydzielania zasobów (pamięci, obiektów zagnieżdżonych, itd.) dla klasy oraz do inicjalizowania pól klasy (np. zerowanie pól). Można utworzyć dowolną liczbę konstruktorów ale tylko jeden destruktor. Jeśli klasa posiada kilka konstruktorów, to muszą się one różnić liczbą i/lub typami przekazywanych argumentów. Destruktor służy do zwalniania zasobów, przydzielonych w konstruktorze lub w trakcie działania obiektu danej klasy. Destruktor nie pobiera żadnych argumentów. Do usuwania niepotrzebnych już w programie obiektów, zaleca się stosowanie metody Free, która sama wywołuje destruktor, wcześniej sprawdzając czy obiekt jeszcze istnieje (jeśli obiekt już nie istnieje, to destruktor nie jest wtedy wywoływany). Zapobiega to powstawaniu przypadkowych błędów w programie, związanych z błędnym gospodarowaniem pamięcią używaną przez obiekt (oczywiście o ile destruktor nie zawiera błędów).
Przykład Object
[edytuj]type Data = object(TObject) Dzien: 1..31; Miesiac: 1..12; Rok: integer; procedure Drukuj; end; procedure Data.Drukuj; begin writeln(Dzien,'.',Miesiac,'.',Rok) end;
Przykład Class
[edytuj]Deklaracja oraz użycie konstruktora i destruktora
type TData = class(TObject) private FDzien: 1..31; FMiesiac: 1..12; FRok: integer; public constructor Create; destructor Destroy; procedure Drukuj; end; constructor TData.Create; begin FDzien := 1; FMiesiac := 5; FRok := 2013; end; destructor TData.Destroy; begin // nic nie robi, bo nie przydzielano klasie żadnych zasobów end; procedure TData.Drukuj; begin Writeln(FDzien, '-', FMiesiac, '-', FRok) end; var Data1: TData; begin Data1 := TData.Create; {...} Data1.Free; end.
Odwołania do klasy
[edytuj]Łącza programowego
[edytuj]Typ wskaźnikowy
[edytuj]Wskaźnik zawiera adres zmiennej. Deklaracja zmiennych typu wskaźnikowego zawiera operator ^ przed nazwą typu, na który ma wskazywać. Kiedy chcemy uzyskać adres zmiennej, poprzedzamy ją operatorem @. Kiedy chcemy się odwołać do elementu wskazywanego przez wskaźnik, piszemy po nazwie wskaźnika ^. Można też tworzyć nowe zmienne dynamiczne, np. procedurą new(wskaźnik) i usuwać je, np. procedurą dispose(wskaźnik).
Przykłady:
[edytuj]program wsk; var wsk1, wsk2: ^integer; i: integer; begin i := 1; wsk1 := @i; if @wsk1^ = wsk1 then writeln('tak'); {drukuje tak} writeln(wsk1^); {drukuje 1} wsk1^ := 2; wsk1 := nil; if wsk1 = nil then writeln('tak'); {drukuje tak} writeln(i); {drukuje 2} new(wsk2); wsk2^ := 3; writeln(wsk2^); {drukuje 3} dispose(wsk2); new(wsk1); wsk2 := wsk1; wsk1^ := 4; writeln(wsk1^); {drukuje 4} readln; dispose(wsk1); {dispose(wsk2); - to byłby błąd} if wsk2 = nil then writeln('tak'); {nic nie drukuje} readln; end.
Typ proceduralny
[edytuj]Typ wariantowy
[edytuj]Zgodność typów
[edytuj]Identyczność typów
[edytuj]Dwa typy a i b są identyczne, jeżeli:
- posiadają ten sam identyfikator typu
- dają się wywieźć od tego samego identyfikatora za pomocą konstrukcji: a=b.
Zgodność operacyjna
[edytuj]Dwa typy są zgodne operacyjne, jeśli są m.in.:
- identyczne,
- typami całkowitymi,
- typami rzeczywistymi,
- jeden jest typem okrojonym drugiego,
- są typami okrojonymi tego samego typu bazowego,
- typami zbiorowymi o zgodnych typach bazowych
- jeden jest typem Pointer, a drugi dowolnym typem wskaźnikowym,
- są typami proceduralnymi o identycznych typach wyników, jednakowej liczbie parametrów i identycznych typach odpowiadających sobie parametrów.
Zgodność w sensie przypisania
[edytuj]Instrukcja przypisania z := w jest poprawna, o ile typ a zmiennej z i typ b wyrażenia w spełniają jeden z warunków:
- są typami rzeczywistymi,
- są typami łańcuchowymi,
- a i b są identyczne, ale nie są typami plikowymi, ani nie zawierają odwołań do typu plikowego,
- a i b są zgodnymi typami porządkowymi i wartość w jest jedną z możliwych wartości typu a,
- a jest typem rzeczywistym, a b typem całkowitym,
- a jest typem łańcuchowym, a b jest typem znakowym,
- są zgodnymi operacyjnie typami zbiorowymi,
- są zgodnymi operacyjnie typami wskaźnikowymi,
- są zgodnymi operacyjnie typami proceduralnymi.
Inne podziały typów
[edytuj]Predefiniowalność
[edytuj]- standardowe – są one predefiniowane i nie wymagają opisu programisty.
- niestandardowe – nie są predefiniowane i muszą być opisane przez programistę.
Uzależnienie od procesora i systemu operacyjnego
[edytuj]- podstawowe – są niezależne od procesora i systemu operacyjnego.
- ogólne – zależą od procesora i systemu operacyjnego.