varip: IShape := new Point(20,30);
ip.Draw;
Point(ip).Print;
Все методы класса, реализующего интерфейс, являются виртуальными без использования ключевых слов virtualили override. В частности, ip.Draw вызовет метод Draw класса Point. Однако, цепочка виртуальности таких методов обрывается. Чтобы продолжить цепочку виртуальности методов, реализующих интерфейс, в подклассах, следует использовать ключевое слово virtual:
type
Point = class(IShape,ICloneable)
...
functionClone: Object; virtual;
begin
Result := new Point(xx,yy);
end;
end;
Для интерфейсов, как и для классов, можно также использовать операции isи as:
ifip isPoint then
...
varp: Point := ip asPoint;
ifp<>nil then
writeln('Преобразование успешно');
Реализация нескольких интерфейсов
Несколько интерфейсов могут содержать одинаковые методы или свойства. При наследовании от таких интерфейсов такие одинаковые методы или свойства сливаются в один:
type
IShape = interface
procedureDraw;
propertyX: integer read;
propertyY: integer read;
end;
IBrush = interface
procedureDraw;
propertySize: integer read;
end;
Brush = class(IShape,IBrush)
// метод Draw реализуется единожды
end;
Чтобы решить проблему с одинаковыми именами в интерфейсах, в .NET классы могут реализовывать методы интерфейсов так называемым явным образом, так что вызов метода интерфейса для переменной класса возможен только после явного приведения к типу интерфейса. В PascalABC.NETтакие классы определять нельзя, однако, пользоваться такими классами, реализованными в .NET, можно. Например, тип integer явно реализует интерфейс IComparable:
vari: integer := 1;
varres : integer := IComparable(i).CompareTo(2);
// i.CompareTo(2) - ошибка компиляции
Обобщенным типом (generic) называется шаблон для создания класса, записи или интерфейса, параметризованный одним или несколькими типами. Класс (запись, интерфейс) образуется из шаблона класса (записи, интерфейса) подстановкой конкретных типов в качестве параметров. Параметры указываются после имени обобщенного типа в угловых скобках. Например, Stack - шаблон класса списка элементов типа T, параметризованный типом T, а Stack - класс списка с элементами типа integer.
Обобщённые подпрограммы описываются здесь.
Для объявления шаблона класса используется следующий синтаксис:
type
Node = class
data: T;
next: Node;
public
constructorCreate(d: T; nxt: Node);
begin
data := d;
next := nxt;
end;
end;
Stack = class
tp: Node;
public
procedurePush(x: T);
begin
tp := newNode(x,tp);
end;
functionPop: T;
begin
Result := tp.data;
tp := tp.next;
end;
functionTop: T;
begin
Result := tp.data;
end;
functionIsEmpty: boolean;
begin
Result := tp = nil;
end;
end;
Использование шаблона класса иллюстрируется ниже:
var
si: Stack;
sr: Stack;
begin
si := newStack;
sr := newStack;
for vari := 1 to10 do
si.Push(Random(100));
while notsi.IsEmpty do
sr.Push(si.Pop);
while notsr.IsEmpty do
write(sr.Pop,' ');
end.
Подстановка конкретного типа-параметра в обобщенный тип называется инстанцированием.
Обобщенные подпрограммы: обзор
Обобщенной подпрограммой (generic) называется подпрограмма, параметризованная одним или несколькими типами. Подпрограмма образуется из обобщенной подпрограммы подстановкой конкретных типов в качестве параметров. Параметры указываются после имени подпрограммы в угловых скобках.
Например, следующая обобщённая функция параметризована одним параметром:
functionFindFirstInArray(a: array ofT; val: T): integer;
begin
Result := -1;
for vari:=0 toa.Length-1 do
ifa[i]=val then
begin
Result := i;
exit;
end;
end;
varx: array ofstring;
begin
SetLength(x,4);
x[0] := 'Ваня';
x[1] := 'Коля';
x[2] := 'Сережа';
x[3] := 'Саша';
writeln(FindFirstInArray(x,'Сережа'));
end.
При вызове обобщенной подпрограммы тип-параметр обобщения можно не указывать, поскольку компилятор выводит типы параметров шаблона по типам фактических параметров. В данном случае после выведения получено: T=string.
Читать дальше