Обобщенные подпрограммы: обзор
Обобщенной подпрограммой (generic) называется подпрограмма, параметризованная одним или несколькими типами. Подпрограмма образуется из обобщенной подпрограммы подстановкой конкретных типов в качестве параметров. Параметры указываются после имени подпрограммы в угловых скобках.
Например, следующая обобщённая функция параметризована одним параметром:
function FindFirstInArray<T>(a: array of T; val: T): integer;
begin
Result := -1;
for var i:=0 to a.Length-1 do
if a[i]=val then
begin
Result := i;
exit;
end;
end;
var x: array of string;
begin
SetLength(x,4);
x[0] := 'Ваня';
x[1] := 'Коля';
x[2] := 'Сережа';
x[3] := 'Саша';
writeln(FindFirstInArray(x,'Сережа'));
end.
При вызове обобщенной подпрограммы тип-параметр обобщения можно не указывать,
поскольку компилятор выводит типы
параметров шаблона по типам фактических параметров. В данном случае после
выведения получено: T=string
.
При выведении требуется точное соответствие типов, приведение типов не допускается. Например, при компиляции следующего кода
...
var x: array of real;
begin
SetLength(x,3);
x[0] := 1;
x[1] := 2.71;
x[2] := 3.14;
writeln(FindFirstInArray(x,1));
end.
произойдет ошибка. Причина состоит в том, что первый параметр имеет тип array of real, а второй - тип integer, что не соответствует ни одному типу T в заголовке обобщенной функции. Для решения проблемы следует либо изменить тип второго параметра на real:
FindFirstInArray(x,1.0)
либо явно после имени функции в угловых скобках указать имя типа, которым параметризован данный вызов:
FindFirstInArray&<real>(x,1)
Использование знака & здесь обязательно, поскольку в противном случае компилятор трактует знак < как "меньше".
Обобщёнными могут быть не только обычные подпрограммы, но и методы классов, а также методы другого обобщённого класса. Например:
type
Pair<T,Q> = class
first: T;
second: Q;
function ChangeSecond<S>(newval: S): Pair<T, S>;
end;
function Pair<T,Q>.ChangeSecond<S>(newval: S): Pair<T,S>;
begin
result := new Pair<T,S>;
result.first := first;
result.second := newval;
end;
var
x: Pair<integer,real>;
y: Pair<integer,string>;
begin
x := new Pair<integer,real>;
x.first := 3;
y := x.ChangeSecond('abc');
writeln(y.first, y.second);
end.
По окончании работы данная программа выведет 3abc.