Интерфейсы: обзор

Интерфейс - это тип данных, содержащий набор заголовков методов и свойств, предназначенных для реализации некоторым классом. Интерфейсы описываются в разделе 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('Преобразование успешно');