Рассмотрим вопросы реализации интерфейсов подробнее.
Объявим два интерфейса:
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 идентична, то можно не создавать два разных метода, а объявить класс следующим образом:
При реализации классов, поддерживающих множество интерфейсов и много методов, может оказаться удобным делегировать реализацию некоторых из них дочерним классам. Рассмотрим пример класса, реализующего два интерфейса:
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;![]() |
![]() |