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.