Перевантаження процедур і функцій
У деяких випадках виникає необхідність в написанні підпрограм, які виконують однакові логічні дії, але над змінними різних типів даних. наприклад:
procedure IncrementInteger (var Value: Integer);
procedure IncrementReal (var Value: Real);
У мові Delphi існує можливість дати двом і більше процедур (функцій) однакові ідентифікатори за умови, що всі такі процедури (функції) відрізняються списком параметрів. Така можливість називається перевантаженням. Для вказівки того, що процедура (функція) перевантажена, служить стандартна директива overload. З її допомогою вищенаведений приклад можна переписати таким чином:
procedure Increment (var Value: Integer); overload; // процедура 1
procedure Increment (var Value: Real); overload; // процедура 2
Яку саме процедуру використовувати в тому чи іншому випадку компілятор буде визначати на етапі компіляції програми за типами фактичних аргументів, переданих при виклику.
var
X: Integer;
Y: Real;
begin
X: = 1;
Y: = 2.0;
Increment (X); // Викликається процедура 1
Increment (Y); // Викликається процедура 2
end.
При перевантаженні процедур і функцій існує особливість, пов'язана з цілочисельними типами даних. Припустимо, є дві процедури:
procedure Print (X: Shortint); overload; // процедура 1
procedure Print (X: Longint); overload; // процедура 2
Якщо ми спробуємо викликати процедуру Print, вказавши в якості фактичного аргументу целочисленную константу, то побачимо, що вибір компілятором варіанти процедури залежить від значення константи.
Print (5); // Викликається процедура 1
Print (150); // Викликається процедура 2
Print (-500); // Викликається процедура 2
Print (-1); // Викликається процедура 1
Очевидно, що одне і те ж число може інтерпретуватися і як Longint, і як Shortint (наприклад, числа 5 і -1). Логіка компілятора в таких випадках така: якщо значення фактичного параметра потрапляє в діапазон значень декількох типів, за якими відбувається перевантаження, то компілятор вибирає процеудуру (функцію), у якій тип параметра має менший діапазон значень. Наприклад, виклик Print (5) буде означати виклик того варіанта процедури, який має тип параметра Shortint. А ось виклик Print (150) означатиме виклик того варіанта процедури, який має тип параметра Longint, тому що число 150 не вміщується в діапазон значень типу даних Shortint.
Оскільки в нинішній версії середовища Delphi Узагальнення тип даних Integer збігається з фундаментальним типом даних Longint, наступний варіант перевантаження є помилковим:
procedure Print (X: Integer); overload;
procedure Print (X: Longint); overload; // Помилка!
Така ж помилка виникає при використанні призначених для користувача типів даних, визначених через загальний базовий тип.
type
TMyInteger = Integer;
procedure Print (X: Integer); overload;
procedure Print (X: TMyInteger); overload; // Помилка!
Що робити в тих випадках, коли таке перевантаження просто необхідна? Для цього призначений для користувача тип даних необхідно створювати з використанням ключового слова type:
type
TMyInteger = type Integer;
procedure Print (X: Integer); overload;
procedure Print (X: TMyInteger); overload; // Правильно
Необхідно зауважити, що при використанні перевантажених процедур (функцій), у яких є параметри, які мають стандартні значення, потрібно бути дуже уважним, тому що можуть виникнути ситуації, коли компілятор просто не знатиме, яку саме процедуру (функцію) ви хочете викликати. наприклад:
procedure Increment (var Value: Real; Delta: Real = 1.0); overload; // процедура 1
procedure Increment (var Value: Real); overload; // процедура 2
Виклик процедури Increment з одним параметром викличе неоднозначність:
var
X: Real;
begin
Increment (X, 10); // Викликається процедура 1
Increment (X); // Помилка! неоднозначність
end.
Забороняється також перевантажувати функції, які відрізняються лише типом значення, що повертається.
function SquareRoot (X: Integer): Single; overload;
function SquareRoot (X: Integer): Double; overload; // Помилка!