Страницы

вторник, 14 апреля 2009 г.

Хотелка для Delphi: поддержка интерфейсов базовыми классами VCL

Я вот тут подумал, что здорово было бы, если бы в Дельфи были определены интерфейсы для базовых классов. Например, был бы интерфейс IList, реализуемый классом TList. IStringList, реализуемый TStringsList и т.п. А особенно классно, было бы если бы были определены интерфейсы реализующие взаимодействие с компонентами.

Например интерфейс:

ICaptionedControl = interface
  property Caption:string;
end;

Если бы все контролы, имеющие свойство Caption(например TLabel; TButton; TCheckBox; TRadioButton; TGroupBox; TBitBtn; TSpeedButton), реализовывали его, было бы намного проще их изменять. Хотя, подобное на практике нужно только, когда начинаешь реализовывать собственный механизм перевода программы.

Пример с Db-control-ами

Более полезным было бы применение интерфейсов в Db-контролах. Например, имея интерфейсы:

IDataSourceProperty = interface
  property Datasource: Idatasource;
end;

IDataFieldProperty = interface
  property DataFieldName:string;
  function GetDataField: IField;
end;

IReadOnly = interface
  property ReadOnly: Boolean;
end;

Можно было бы упростить работу с Db-контролами в разы, просто проверяя, реализует ли контрол соответствующий интерфейс. Это было бы полезно для обработки прав доступа в программе. Например, если у пользователя нет прав на работу с определённым полем в базе, то и в приложении, все контролы использующие данное поле можно спрятать, или сделать их доступными только для чтения.

А то сейчас, чтобы реализовать что-то подобное, приходится либо использовать TypInfo, либо проверять классы вручную:

procedure ValidateControlsField(Sender: TObject);
var
  tmpField: Tfield;
begin
If aControl is TDbEdit then
  tmpField := TDbEdit(aControl).DataField
else If aControl is TDbMemo then
  tmpField := TDbMemo(aControl).DataField
else If aControl is TDbComboBox then
  tmpField := TDbComboBox(aControl).DataField;
end;

А всё потому, что TDbEdit наследуется от TCustomMaskEdit, TDbComboBox от TCustomComboBox, а TDbMemo от TCustomMemo.

В случае с интерфейсами, код выглядел бы примерно так:

procedure ValidateControlsField(Sender: TObject);
var
  tmpDataFieldPropertyI: IDataFieldProperty;
begin
  if Supports(Sender, IDataFieldProperty, tmpDataFieldPropertyI) then
  begin
    // работаем с Tfield, точнее IField
  end; 
end;

Где ещё это было бы полезно?

Если в приложении вместо приведения типов, использовать интерфейсы, это увеличит возможность повторного использования кода.

При создании расширений(плагинов).

Можно было бы вводить поддержку плагинов, использующих функционал классов, без возни с COM или BPL(которые требуют, чтобы и exe и bpl были скомпилированы одной версией компилятора).

Автоматическое уничтожение объектов. Вводить меньше кода.

Вместо того, чтобы писать так:

procedure SomeProcedure; 
var tmpSL: TStringList; 
begin 
  tmpSL:= TStringList.Create; 
  try 
    // работаем с tmpSL
  finally 
    tmpSL.Free; 
  end; 
end;

Можно было бы писать так:

procedure SomeProcedure; var tmpSL: IStringList; begin tmpSL:= TStringList.Create; // работаем с tmpSL end; // tmpSL будет автоматически освобождена.


Самое главное

Станет намного легче менять реализацию. Если работа будет идти через интерфейсы, то станет намного проще заменить один класс другим. Особенно в случае замены одного набора компонентов, другим.

Например:

Сейчас у меня в проектах используются стандартные Db-контролы(TDbEdit, TDbComboBox). Чтобы заменить из на другие аналогичные Db-контролы(например Ehlib-овские), придётся заменить компоненты на форме, а также пройтись по коду в поисках явной проверки типов(if Sender is TDbEdit then …). Если бы были интерфейсы, и в коде использовались они, то, многое бы работало без изменений.

Давайте обсудим

Что вы думаете об этой идее?

p.s. У Delphi появился форум на UserVoice. И я добавил туда эту идею. Пожалуйста проголосуйте за неё(можно голосовать без регистрации):

Add interface support for basic VCL classes

p.p.s. Мне очень не нравится интерфейс QC. =(  Но я кое-как разобрался, и с помощью встроенной в Delphi QC Tool с мегаужасным интерфейсом добавил отчёт: QC#73087

p.p.p.s. Если не сложно, то проголосуйте ещё за поддержку Firebird в Delphi.(навряд ли это, что-то изменит, но не попытаться я не могу=))

p.p.p.s. Обсуждение этой темы на Винграде

Ссылки по теме

Пример, показывающий как добавить поддержку своих интерфейсов в VCL.

4 комментария:

  1. Идея хорошая (самому в голову такое приходило), но навряд ли будет реализована. Слишком несопоставимы затраченные на неё усилия и полезная отдача.

    ОтветитьУдалить
  2. Кстати, было бы неплохо создать эту тему как Suggestion на QC ;)

    ОтветитьУдалить
  3. Алексей в своем блоге написал решение данного вопроса
    http://kazav.blogspot.com/2009/04/delphi.html

    ОтветитьУдалить