ИНТЕРФЕЙСЫ
Интерфейсы играют главную роль в технологиях СОМ (Component Object Model - компонентная модель объектов), CORBA (Common Object Request Broker Architecture - архитектура с брокером требуемых общих объектов) и связанных с ними технологиях удаленного доступа, т. е. технологиях доступа к объектам, расположенным (и выполняющимся) на другой машине. Их основная задача - описать свойства, методы и события удаленного объекта в терминах машины клиента, т. е. на используемом при разработке клиентского приложения языке программирования. С помощью интерфейсов программа клиента обращается к удаленному объекту так, как если бы он был ее собственным объектом. Тема интерфейсов достаточно обширна и интересна. В этой лекции даются лишь самые общие сведения об интерфейсах. Сведение этой темы в одну лекцию с классами не случайно, т. к. интерфейс представляет собой пустой класс, т. е. класс, в котором провозглашены, но никак не расшифрованы свойства и методы. 9.4.1. Создание и использование интерфейса Интерфейсы представляют собой частный случай описания типов. Они объявляются с помощью зарезервированного слова interface. Например: Type IEdit = interface procedure Copy; stdcall; procedure Cut; stdcall; procedure Paste; stdcall; function Undo: Boolean; stdcall; End; Такое объявление эквивалентно описанию абстрактного класса в том смысле, что провозглашение интерфейса не требует расшифровки объявленных в нем свойств и методов. В отличие от классов интерфейс не может содержать поля, и, следовательно, объявляемые в нем свойства в разделах read и write могут ссылаться только на методы. Все объявляемые в интерфейсе члены размещаются в единственной секции public. Методы не могут быть абстрактными (abstract), виртуальными (virtual), динамическими (dynamic) или перекрываемыми (override). Интерфейсы не могут иметь конструкторов или деструкторов, т. к. описываемые в них методы реализуются только в рамках поддерживающих их классов, которые называются интерфейсными. Если какой-либо класс поддерживает интерфейс (т. е. является интерфейсным), имя этого интерфейса указывается при объявлении класса в списке его родителей: TEditor = class(TInterfacedObject,IEdit) Procedure Copy; stdcall; Procedure Cut; stdcall; procedure Paste; stdcall; function Undo: Boolean; stdcall; End; В отличие от обычного класса интерфейсный класс может иметь более одного родительского интерфейса: Type IMylnterface = interface procedure Delete; stdcall; End; TMyEditor = class(TInterfacedObiect, lEdit, IMylnterface) Procedure Copy; stdcall; Procedure Cut; stdcall; procedure Paste; stdcall; function Undo:, Boolean; stdcall; procedure Delete; stdcall; End; В любом случае в разделе реализации интерфейсного класса необходимо описать соответствующие интерфейсные методы. Если, например, объявлен интерфейс IPaint = interface procedure CirclePaint(Canva: TCanvas; X,Y,R: Integer); procedure RectPaint(Canva: TCanvas; X1,Y1,X2,Y2: Integer); End; и использующий его интерфейсный класс TPainter = class(TInterfacedObject,IPaint) procedure CirclePaint(Canva: TCanvas; X,Y,R: Integers); End; то в разделе implementation следует указать реализацию методов: procedure TPainter.CirclePaint(Canva: TCanvas; X,Y,R: Integers; begin with Canva do Ellipse(X, Y, X+2*R, Y+2*R); End; procedure TPainter.RectPaint(Canva: TCanvas; X1,Y1,X2,Y2: Integer); Begin with Canva do Rectangle(XI, Yl, X2, Y2) End; Теперь можно объявить интерфейсный, объект класса TPainter, чтобы с его помощью нарисовать окружность и квадрат: procedure TFormI.PaintBoxIPaint(Sender: TObject); Var Painter: IPaint; Begin Painter:= TPainter.Create; Painter.CirclePaint(PaintBoxl.Canvas,10,0,10); Painter.RectPaint(PaintBoxl.Canvas,40,0,60,20); End; Несмотря на то что интерфейс всегда объявляется до объявления использующего его интерфейсного класса и, следовательно, известен компилятору, его методы обязательно должны быть перечислены в объявлении класса. В нашем случае простое указание Type TPainter = class(TInterfacedObject, IPaint) End; было бы ошибкой: компилятор потребовал бы вставить описание методов CirclePaint и RectPaint. Подобно тому как все классы в Object Pascal порождены от единственного родителя TObject, все интерфейсные классы порождены от общего предка TInterfacedObject. Этот предок умеет распределять память для интерфейсных объектов и использует глобальный интерфейс lunknow: Type TInterfacedObject = class(TObject, lUnknown) private FRefCount: Integer;
|