ДельфинарийСтатьи

Использование интерфейсов

Автор:


Статья находится в разработке

Простой интерфейс
Агрегирование
Имплементация
  делегирование
  агрегирование
Наследование интерфейсов

Простой интерфейс


Нужен для отделения декларируемых возможностей класса от непосредственной реализации.
type
 ISomeInterface = interface
  function ReturnSomething(aP: string): integer;
  procedure DoSomething;
  procedure DoSomethingElse(var r: single);stdcall;
 end;

 TRealization = class(TInterfacedObject, ISomeInterface)
 private
  function GetSomething(aP: string): integer;
  procedure DoSomething;//Реализация не обязательно должна быть в области public
 public
  function ISomeInterface.ReturnSomething = GetSomething;//переопределяем реализацию
  procedure DoSomethingElse(var r: single);stdcall;
  destructor Destroy;override;
 end;

procedure DoSomethingElse(obj: ISomeInterface);
var
 r: single;
begin
 obj.DoSomethingElse(r);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
 Some: ISomeInterface;
begin
 Some:= TRealization.Create;
 Some.DoSomething;
 Some.ReturnSomething('ff');
 DoSomethingElse(Some);
 //Не нужно делать Some.Free! Сам дохнит:)
end;

Агрегирование


Один объект обладает несколькими свойствами.
Основная особенность - для таких объектов нужно вручную делать _AddRef и _Relize. В хелпе об этом почему-то умалчивается, но факт остается фактом. Я в своё время долго стучал головой об стекло монитора:)
type
 IFeature1 = interface
  procedure DoOne;
 end;

 IFeature2 = interface
  procedure DoTwo;
 end;

 IFeature3 = interface
  procedure DoThree;
 end;

 TMultiObject = class(TInterfacedObject, IFeature1, IFeature2, IFeature3)
  procedure DoOne;   //реализация фичи1
  procedure DoTwo;   //реализация фичи2
  procedure DoThree; //реализация фичи3
  constructor Create;
  destructor Destroy;override;
 end;


//В эти функции можно передовать любые классы поддерживающие
//заданные интерфейсы
procedure CallFeature1(Obj: IFeature1);
begin
 Obj.DoOne;
end;

procedure CallFeature2(Obj: IFeature2);
begin
 Obj.DoTwo;
end;

procedure CallFeature3(Obj: IFeature3);
begin
 Obj.DoThree;
end;

constructor TMultiObject.Create;
begin
 Self._AddRef; //!!!!!!
end;


//Тестируем
procedure TForm1.Button2Click(Sender: TObject);
var
 MultObj: TMultiObject;
begin
 MultObj:= TMultiObject.Create;

 MultObj.DoOne;   //явно вызываем методы
 MultObj.DoTwo;
 MultObj.DoThree;

 CallFeature1(MultObj); //Передаем объект в том виде,
 CallFeature2(MultObj); //в котором его хочет получить
 CallFeature3(MultObj); //функция

 MultObj._Release; //!!!!!!
end;

Имплементация

делегирование


Выносим из реализации класса реализации отдельных фрагментов
type

 //Декларируем свойства для объекта.
 //Их реализация нас не волнует.
 IDeclaredOptions = interface
  procedure Metod1;
  procedure Metod2;
  procedure Metod3;
 end;

 TSuperManager = class
 private
  FRealization: IDeclaredOptions;
  //...
 public
  property Realization: IDeclaredOptions read FRealization write FRealization;
 end;


 //реализации могут быть абсолютно любыми классами,
 //могут поддерживать дополнительные интерфейсы и
 //быть унаследованными от разных предков
 TRealization1 = class( TInterfacedObject, IDeclaredOptions)
  procedure Metod1;
  procedure Metod2;
  procedure Metod3;
 end;

 TRealization2 = class( TInterfacedObject, IDeclaredOptions)
  procedure Metod1;
  procedure Metod2;
  procedure Metod3;
 end;


procedure TForm1.Button2Click(Sender: TObject);
var
 SM: TSuperManager;
begin
 SM:= TSuperManager.Create;

 if random(100)>50 then
  SM.Realization:= TRealization1.Create
 else
  SM.Realization:= TRealization2.Create;

 SM.Realization.Metod1;

 SM.Free;
end;

агрегирование


Выносим из реализации класса реализацию отдельного интерфейса
type
 IDeclaredFeature = interface
  procedure Metod1;
 end;

 TFeature = class(TInterfacedObject, IDeclaredFeature,...)
 private
  FRealization: IDeclaredFeature;
  ....
 public
  property Realization: IDeclaredFeature read FRealization write FRealization implements IDeclaredFeature;
 end;


 TFeatRealization = class( TInterfacedObject, IDeclaredFeature)
  procedure Metod1;
  ///
  constructor Create;
  destructor Destroy;override;
 end;


procedure PassAsDeclaredFeature(obj: IDeclaredFeature);
begin
 obj.Metod1;
end;


procedure TForm1.Button4Click(Sender: TObject);
var
 Feat: TFeature;
begin
 Feat:= TFeature.Create;
 Feat.Realization:= TFeatRealization.Create;

 Feat.Realization.Metod1;
 PassAsDeclaredFeature(Feat);

 Feat.Realization._Release;//!!! Очередной прикол от Борланд:)
end;

Наследование интерфейсов


Интерфейсы можно наследовать друг от друга.
type
 IA = interface
  procedure DoA;
 end;

 IB = interface (IA)
  procedure DoB;
 end;

 IC = interface (IA)
  procedure DoC;
 end;


 TObjB = class( TInterfacedObject, IB)
  procedure DoA;
  procedure DoB;
  ///
  constructor Create;
  destructor Destroy;override;
 end;

 TObjC = class( TInterfacedObject, IC)
  procedure DoA;
  procedure DoC;
  ///
  constructor Create;
  destructor Destroy;override;
 end;


 TObjAB = class(TObjB, IA)
 end;

procedure DoA(Obj: IA);
begin
 Obj.DoA;
end;

procedure TForm1.Button4Click(Sender: TObject);
var
 B:  IB;
 C:  IC;
 //
 OB: TObjB;
 OAB: TObjAB;
begin
 B:= TObjB.Create;
 C:= TObjC.Create;
 OAB:= TObjAB.Create;
 OAB._AddRef;

 B.DoB;
 C.DoC;

 DoA(B); //Так делать можно
 DoA(C);

 DoA(OB);//А так нет!!!
 DoA(OAB);//Надо вот так!

 OAB._Release;
end;


С наилучшими пожеланиями,
DROник (с) 2005

24 ноября 2005

Комментарии [21]