Delphi и COM


         

Реализация интерфейсов (расширенное рассмотрение)


Рассмотрим вопросы реализации интерфейсов подробнее.

Объявим два интерфейса:

type   ITest = interface   ['{61F26D40-5CE9-11D4-84DD-F1B8E3A70313}']     procedure Beep;   end;     ITest2 = interface   ['{61F26D42-5CE9-11D4-84DD-F1B8E3A70313}']     procedure Beep;   end;

Теперь создадим класс, который будет реализовывать оба этих интерфейса:

  TTest2 = class(TInterfacedObject, ITest, ITest2)     procedure Beep1;     procedure Beep2;     procedure ITest.Beep = Beep1;     procedure ITest2.Beep = Beep2;   end;

Как видно, класс не может содержать сразу два метода Beep. Поэтому Delphi предоставляет способ для разрешения конфликтов имен, позволяя явно указать, какой метод класса будет служить реализацией соответствующего метода интерфейса.

Если реализация методов TTest2.Beep1 и TTest2.Beep2 идентична, то можно не создавать два разных метода, а объявить класс следующим образом:


  TTest2 = class(TInterfacedObject, ITest, ITest2)     procedure MyBeep;     procedure ITest.Beep = MyBeep;     procedure ITest2.Beep = MyBeep;   end;

При реализации классов, поддерживающих множество интерфейсов и много методов, может оказаться удобным делегировать реализацию некоторых из них дочерним классам. Рассмотрим пример класса, реализующего два интерфейса:

type   TBeeper = class     procedure Beep;   end;     TMessager = class     procedure ShowMessage(const S: String);   end;     TTest3 = class(TInterfacedObject, ITest, IAnotherTest)   private     FBeeper: TBeeper;     FMessager: TMessager;     property Beeper: TBeeper read FBeeper implements ITest;     property Messager: TMessager read FMessager implements IAnotherTest;   public     constructor Create;     destructor Destroy; override;   end;

Для делегирования реализации интерфейса другому классу служит ключевое слово implements.

{ TBeeper } procedure TBeeper.Beep; begin   Windows.Beep(0,0); end;   { TMessager } procedure TMessager.ShowMessage(const S: String); begin   MessageBox(0, PChar(S), NIL, 0); end;   { TTest3 } constructor TTest3.Create; begin   inherited;   // Создаем экземпляры дочерних классов   FBeeper := TBeeper.Create;   FMessager := TMessager.Create; end;   destructor TTest3.Destroy; begin   // Освобождаем экземпляры дочерних классов   FBeeper.Free;   FMessager.Free;   inherited; end;

Такой подход позволяет разбить реализацию сложного класса на несколько простых, что упрощает программирование и повышает модульность программы.

Обращаться к полученному классу можно точно так же, как и к любому классу, реализующему интерфейсы:

var   Test: ITest;   Test2: IAnotherTest; begin   Test2 := TTest3.Create;   Test2.ShowMessage('Hi');   Test := Test2 as ITest;   Test.Beep; end;


Содержание раздела