Интерфейсы: обзор
Интерфейс - это
тип данных, содержащий набор заголовков методов и свойств, предназначенных для
реализации некоторым классом. Интерфейсы описываются в разделе type
следующим образом:
ИмяИнтерфейса
=
interface
объявления методов и свойствend
;
Для метода приводится только заголовок, для свойства после возвращаемого типа указываются необходимые модификаторы доступа read и write.
Например:
type
IShape = interface
procedure Draw;
property X: integer read;
property Y: integer read;
end;
ICloneable = interface
function Clone: Object;
end;
Поля и статические методы не могут входить в интерфейс.
Класс реализует интерфейс, если он реализует все методы и
свойства интерфейса в
public
-секции. Если
класс не реализует хотя бы один метод или свойство интерфейса, возникает ошибка
компиляции. Класс может реализовывать также несколько интерфейсов. Список
реализуемых интерфейсов указывается в скобках после ключевого слова
class
(если указано имя предка, то после имени предка).
Например:
type
Point = class(IShape,ICloneable)
private
xx,yy: integer;
public
constructor Create(x,y: integer);
begin
xx := x; yy := y;
end;
procedure Draw; begin end;
property X: integer read xx;
property Y: integer read yy;
function Clone: Object;
begin
Result := new Point(xx,yy);
end;
procedure Print;
begin
write(xx,' ',yy);
end;
end;
Интерфейсы можно наследовать друг от друга:
type
IPosition = interface
property X: integer read;
property Y: integer read;
end;
IDrawable = interface
procedure Draw;
end;
IShape = interface(IPosition,IDrawable)
end;
Интерфейс по-существу представляет собой абстрактный класс без реализации входящих в него методов. Для интерфейсов, в частности, применимы все правила приведения типов объектов: тип объекта, реализующего интерфейс, может быть неявно приведен к типу интерфейса, а обратное преобразование производится только явно и может вызвать исключение при невозможности преобразования:
var ip: IShape := new Point(20,30);
ip.Draw;
Point(ip).Print;
Все методы класса, реализующего интерфейс, являются
виртуальными без использования ключевых слов virtual
или override
. В
частности, ip.Draw
вызовет метод
Draw
класса Point
.
Однако, цепочка виртуальности таких методов обрывается. Чтобы продолжить цепочку
виртуальности методов, реализующих интерфейс, в подклассах, следует использовать
ключевое слово virtual
:
type
Point = class(IShape,ICloneable)
...
function Clone: Object; virtual;
begin
Result := new Point(xx,yy);
end;
end;
Для интерфейсов, как и для классов, можно также использовать
операции is
и as
:
if ip is Point then
...
var p: Point := ip as Point;
if p<>nil then
writeln('Преобразование успешно');