Как использовать интерфейс с классами VCL? - PullRequest
2 голосов
/ 10 января 2012

В моем предыдущем вопросе мне предложили использовать интерфейс: Как реализовать идентичные методы с 2 и более классами?

Но ничего не соответствует, так как я не знаю, как использовать интерфейсы.

Я думаю, вы можете назвать этот код псевдо:)

type
  IDoSomething = interface
    ['{EFE0308B-A85D-4DF3-889C-40FBC8FE84D0}']
    procedure DoSomething1;
    procedure WMSize(var Message: TWMSize); message WM_SIZE; // <- Unknown directive: 'message'
  end;

  TMyCheckBox = class(TCheckBox, IDoSomething) // <- Undeclared identifier: 'DoSomething1'
  end;

  TMyRadioButton = class(TRadioButton, IDoSomething) // <- Undeclared identifier: 'DoSomething1'
  end;

implementation

procedure IDoSomething.DoSomething1; // Identifier redeclared: 'IDoSomething'
begin
  // do the same thing for TMyCheckBox and TRadioButton
end;

procedure IDoSomething.WMSize(var Message: TWMSize);
begin
  // handle this message the same as with TMyCheckBox and TRadioButton
end;

Как использовать интерфейс для централизации кода? и как я могу поделиться новыми свойствами с помощью интерфейса?

Ответы [ 3 ]

3 голосов
/ 10 января 2012
  1. ключевое слово сообщения не допускается в объявлении метода интерфейса. Удалите message WM_SIZE;, и код будет работать нормально, пока компилятор не решит вторую проблему - см. Ниже

  2. Методы интерфейса никогда не имеют своих собственных реализаций. Если интерфейс IDoSomething объявляет метод DoSomething1, компилятор не позволит написать реализацию, подобную procedure IDoSomething.DoSomething1;, как в вашем коде - вместо этого класс, реализующий интерфейс, должен предоставить тело реализации. 1012 *

2 голосов
/ 10 января 2012

Это моя точка зрения:

1) Вы не можете включить в определение интерфейса

procedure WMSize(var Message: TWMSize); message WM_SIZE;

потому что это на самом деле динамический метод:

Помните, что методы в определении интерфейса не могут быть объявлены как virtual , dynamic , abstract или override .

2) Включая в определение интерфейса

procedure WMSize(var Message: TWMSize);

- это нонсенс, так как это не сигнатура метода, предназначенного для дальнейшей реализации.

Тогда определение интерфейса должно быть голым:

type
 IDoSomething = interface
   ['{EFE0308B-A85D-4DF3-889C-40FBC8FE84D0}']
   procedure DoSomething1;
 end;

Следующие определения классов остаются без изменений (то же самое для их реализаций):

TMyCheckBox = class(TCheckBox, IDoSomething)
  procedure DoSomething1;
  procedure WMSize(var Message: TWMSize); message WM_SIZE;
end;

TMyRadioButton = class(TRadioButton, IDoSomething) 
  procedure DoSomething1;
  procedure WMSize(var Message: TWMSize); message WM_SIZE;
end;


implementation

procedure TMyCheckBox.DoSomething1;
begin
  //
end;

procedure TMyCheckBox.WMSize(var Message: TWMSize);
begin
  //
end;

{ TMyRadioButton }

procedure TMyRadioButton.DoSomething1;
begin
  //
end;

procedure TMyRadioButton.WMSize(var Message: TWMSize);
begin
  //
end;
1 голос
/ 10 января 2012

Как следует из названия: Интерфейсы - это декларация интерфейса, а не реализации.И это именно то, для чего они.Они дают вам возможность вызывать подпрограммы в разных классах, даже если вы ничего не знаете о классе.
А поскольку разные классы могут реализовывать один и тот же интерфейс, реализация может быть совершенно разной.Ваш код должен выглядеть так:

type
  IDoSomething = interface
    ['{EFE0308B-A85D-4DF3-889C-40FBC8FE84D0}']
    procedure DoSomething1;
    procedure WMSize(var Message: TWMSize); 
  end;

  TMyCheckBox = class(TCheckBox, IDoSomething)
  public
    procedure DoSomething1;
    procedure WMSize(var Message: TWMSize); message WM_SIZE;
  end;

  TMyRadioButton = class(TRadioButton, IDoSomething) 
    procedure DoSomething1;
    procedure WMSize(var Message: TWMSize); message WM_SIZE;
  end;

implementation

procedure TMyCheckBox.DoSomething1; 
begin
  // do the same thing for TMyCheckBox and TRadioButton
end;

procedure TMyCheckBox.WMSize(var Message: TWMSize);
begin
  // handle this message the same as with TMyCheckBox and TRadioButton
end;

procedure TMyRadioButton.DoSomething1; 
begin
  // do the same thing for TMyCheckBox and TRadioButton
end;

procedure TMyRadioButton.WMSize(var Message: TWMSize);
begin
  // handle this message the same as with TMyCheckBox and TRadioButton
end;
...