Proceduri și funcții de supraîncărcare
În unele cazuri, este necesar să scrieți subrutine care efectuează aceleași operații logice, dar peste variabilele diferitelor tipuri de date. De exemplu:
procedura IncrementInteger (var Valoare: Integer);
procedura IncrementReal (var Value: Real);
În Delphi, este posibil să se dea două sau mai multe proceduri (funcții) aceleași identificatori, cu condiția ca toate aceste proceduri (funcții) să difere într-o listă de parametri. Această posibilitate se numește supraîncărcare. Pentru a indica faptul că procedura (funcția) este supraîncărcată, este utilizată directiva standard de suprasarcină. Cu ajutorul său, exemplul de mai sus poate fi rescris după cum urmează:
incrementarea procedurii (var Value: Integer); suprasarcină; // procedura 1
incrementarea procedurii (var Value: Real); suprasarcină; // procedura 2
Ce fel de procedură să utilizați în acest sau acel caz compilatorul va determina la etapa de compilare a programului, prin tipurile de argumente reale transmise la apel.
var
X: Integer;
Y: Real;
începe
X: = 1;
Y: = 2,0;
Creștere (X); // Procedura de apel 1
Creștere (Y); // Procedura de apel 2
end.
Atunci când procedurile și funcțiile de supraîncărcare există, există o caracteristică asociată tipurilor de date întregi. Să presupunem că există două proceduri:
procedură Print (X: Shortint); suprasarcină; // procedura 1
procedură Print (X: Longint); suprasarcină; // procedura 2
Dacă încercăm să apelam procedura Print prin specificarea unei constante întregi ca argument real, atunci vedem că alegerea opțiunii de procedură de către compilator depinde de valoarea constantei.
Imprimare (5); // Procedura de apel 1
Imprimare (150); // Procedura de apel 2
Imprimare (-500); // Procedura de apel 2
Imprimare (-1); // Procedura de apel 1
Evident, același număr poate fi interpretat ca și Longint și Shortint (de exemplu, numerele 5 și -1). În astfel de cazuri, logica compilatorului este următoarea: dacă valoarea parametrului actual se încadrează în intervalul mai multor tipuri de valori peste care se produce suprasarcina, compilatorul selectează o procedură (funcție) a cărei parametru are un interval mai mic de valori. De exemplu, un apel la Print (5) va însemna apelarea unei variante a procedurii care are tipul de parametru Shortint. Dar apelul la Print (150) va însemna apelarea variantei procedurii, care are tipul parametrului Longint, deoarece numărul 150 nu se încadrează în domeniul de valori al tipului de date Shortint.
Deoarece în versiunea actuală a mediului Delphi tipul bogat de date Integer este același cu tipul de date Longint, următoarea opțiune de suprasarcină este incorectă:
procedură Imprimare (X: Integer); suprasarcină;
procedură Print (X: Longint); suprasarcină; // Eroare!
Aceeași eroare se întâmplă atunci când se utilizează tipuri personalizate de date definite printr-un tip de bază comun.
tip
TMyInteger = Integer;
procedură Imprimare (X: Integer); suprasarcină;
procedură Print (X: TMyInteger); suprasarcină; // Eroare!
Ce trebuie făcut în cazurile în care o astfel de supraîncărcare este pur și simplu necesară? Pentru a face acest lucru, trebuie să creați un tip de date personalizat utilizând cuvântul cheie de tip:
tip
TMyInteger = tip Integer;
procedură Imprimare (X: Integer); suprasarcină;
procedură Print (X: TMyInteger); suprasarcină; // Corect
Trebuie remarcat faptul că atunci când se utilizează proceduri (funcții) supraîncărcate care au parametri care au valori standard, trebuie să fii foarte atent, deoarece pot exista situații în care compilatorul nu știe pur și simplu care este procedura (funcția) pe care doriți să o apelați. De exemplu:
incrementarea procedurii (var Value: Real; Delta: Real = 1.0); suprasarcină; // procedura 1
incrementarea procedurii (var Value: Real); suprasarcină; // procedura 2
Apelarea procedurii de incrementare cu un parametru va cauza ambiguitate:
var
X: Real;
începe
Creștere (X, 10); // Procedura de apel 1
Creștere (X); // Eroare! ambiguitate
end.
De asemenea, este interzisă supraîncărcarea funcțiilor care diferă numai în tipul valorii returnate.
Funcția SquareRoot (X: Integer): Single; suprasarcină;
funcția SquareRoot (X: Integer): dublă; suprasarcină; // Eroare!