Рефакторинг наследования TFrame - PullRequest
3 голосов
/ 26 февраля 2009

Еще один вопрос от зарегистрированного компонента TFrame от меня. Спасибо за помощь, коллеги программисты. :)

Игра с предложением Дарриана о наследовании TFrame здесь :

Особенности:

По сути, у меня есть компонент на основе TFrame, который я зарегистрировал в IDE, и он прекрасно работает. Сейчас я занимаюсь разработкой нескольких «сестринских» компонентов, которые будут в значительной степени разделять невизуальную функциональность и свойства существующего компонента. Поэтому имеет смысл перенести большую часть этого в родительский / суперкласс, от которого могут наследовать как новый, так и старый компоненты.

Каков наилучший способ «рефакторинга» наследования TFrame таким способом? (Это может относиться и к потомкам класса TForm, не уверен). На какие предостережения и вещи стоит обратить внимание?

Пример:

Я пытался, например, создать новый TFrame, на котором ничего нет, и вызвать этот фрейм TMyBaseFrame. Затем изменил определение класса моего существующего компонента (назовем его TMyFrameTreeView), чтобы наследовать от него, а не от TFrame.

Он скомпилировался нормально, но когда я попытался сбросить его на форму, я получил «ClientHeight not found» (или «свойство ClientHeight not found»), и оно не выпало на форму. Удаление ClientHeight и ClientWidth из соответствующего DFM привело к хаосу, и они все равно были заменены при изменении размера. Я заметил ExplicitHeight и ExplicitWidth в дочерних классах, и я думаю, что это связано с переопределением значения свойства из унаследованных значений, но я не уверен. Воссоздание совершенно нового фрейма через New -> Inherited Items, а затем копирование всего, также не дало больших результатов.

Финальная нота

Я понимаю, что это может быстро запутаться, с потоковыми файлами DFM и несколькими поколениями потомков и т. Д., И поэтому я прошу общий концептуальный аспект «на что обращать внимание», но также дать конкретную реальную более простую версию проблемы, а также (что, мне кажется, должно быть выполнимо).

Я создал небольшой тестовый пакет, чтобы разбираться в попытках обучения, и я многому учусь, но он медленный, и любое руководство / понимание от вас, Delphi, «Мастера джедаев», будет высоко оценено. :)



Ответ обновить позже:

Оба ответа ниже были полезны. Кроме того, создание «Базового класса фрейма», в котором НЕТ изменений по сравнению с обычным TFrame, и ТО, что наследуется от него перед добавлением каких-либо свойств, методов и т. Д., По-видимому, значительно стабилизирует потоковую передачу наследования. Не уверен, почему, но пока что это так.

Ответы [ 2 ]

9 голосов
/ 26 февраля 2009

В дополнение к изменению базового класса TMyFrameTreeView на TMyBaseFrame измените первое слово в файле dfm для TMyFrameTreeView с object на inherited.

4 голосов
/ 26 февраля 2009

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

Какой самый лучший способ «рефакторинга» TFrame наследование таким образом?

Суть вашего вышеприведенного текста, возможно, заключается в "невизуальной функциональности компонента". Так что, в этом случае, ИМХО, лучше разделить визуальный и невизуальный слои.

Итак, возможно, лучше использовать декоратор:

TMySharedEngine = class(Whatever)
property LinkedFrame: TFrame;
property P1;
property P2;
...
procedure Proc1;
procedure Proc2;
... //etc.
end;

и в ваших «сестринских» кадрах использовать его экземпляры:

var
TMyFrame1 = class(TFrame)
...
FDecorator: TMySharedEngine;
  ...
  public
  property MySharedPart: TMySharedEngine read FDecorator;
  constructor Create(AOwner: TComponent); override;
  ...
end;

constructor TMyFrame1.(AOwner: TComponent); override;
begin
  inherited;
  FDecorator:=TMySharedEngine.Create; //ok, ok do not forget to Free it .Destroy
  FDecorator.LinkedFrame:=Self;
  ...
end;

OTOH, если вы хотите использовать свой подход, вы можете использовать визуальное наследование форм (как предложил Дариан) или (более гибко) вы можете сделать это вручную: создайте с помощью IDE следующие фреймы: TBaseFrame, TChildFrame1, TChildFrame2. ... и т. д. Теперь перейдите к модулю TChildFrame1 и вручную измените его определение класса с TChildFrame1 = class (TFrame) на TChildFrame1 = class (TBaseFrame). Компиляция. Он должен работать. Тем не менее, рекомендуется, чтобы при выполнении этого трюка TBaseFrame был пустым, чтобы избежать возможных мелких причуд (коллизий функций и т. Д.)

НТН.

...