Delphi: как переместить класс из модуля, избежать циклических ссылок

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

у меня есть модуль с некоторыми классами (и некоторыми перечислениями и константами). Все узнают щелкните и щелкните братьев-кулачков:

unit Cartalk;

interface

type
   TSolution = (solTransmission, solBrakes, solGremlins);

   TTappetBrother = class(TObject)
   public
      function GetSolution: TSolution; virtual; abstract;
   end;

   TClick = class(TTappetBrother)
   public      
      function GetSolution: TSolution; override;
   end;

   TClack = class(TTapperBrother)
   public
      function GetSolution: TSolution; override;
   end;

implementation

function TClick.GetSolution: TSolution;
begin
   Result := solTransmission;
end;

function TClack.GetSoltution: TSolution;
begin
   Result := solGremlins;
end;

end.

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

Моя первая трещина в этом была бы:

unit Cartalk;

interface

uses
   Cartalk_Click, Cartalk_Clack;

type
   TSolution = (solTransmission, solBrakes, solGremlins);

   TTappetBrother = class(TObject)
   public
      function GetSolution: TSolution; virtual; abstract;
   end;

   TClick = Cartalk_Click.TClick; //alias brought in from Cartalk_Click.pas

   TClack = Cartalk_Clack.TClack; //alias brought in from Cartalk_Clack.pas

 implementation

 end.

Отлично, у меня есть все те же классы, доступные в Cartalk.pas, теперь мне просто нужно написать Cartalk_Click.pas и Cartalk_Clack.pas:

unit Cartalk_Click;

interface

type
   TClick = class(TTappetBrother)
   public      
      function GetSolution: TSolution; override;
   end;

implementation

function TClick.GetSolution: TSolution;
begin
   Result := solTransmission;
end;

end.

Проблема, конечно, в том, что TTappetBrother и TSolution в этом блоке не объявлены. Итак, мы добавляем ссылку на то, где они живут, к uses, смотрим, как это терпит неудачу, и достигаем сути моего вопроса:

unit Cartalk_Click;

interface

uses
   Cartalk;

type
   TClick = class(TTappetBrother)
   public      
      function GetSolution: TSolution; override;
   end;

implementation

function TClick.GetSolution: TSolution;
begin
   Result := solTransmission;
end;

end.

Теперь между Cartalk и Cartalk_Click есть циклическая ссылка.

Примечание: Конечно, у меня нет модуля Cartalk, с Click and Clack, братьями-тапперами - это просто пример. На самом деле у меня есть 3 класса, 20 перечислений и 293 константы в моем модуле.


person Ian Boyd    schedule 21.10.2010    source источник
comment
Tappet (например, коснитесь его) Братья. Просто говорю'   -  person Larry Lustig    schedule 22.10.2010
comment
Редактировать: исправлена ​​одна опечатка в таппете.   -  person Ian Boyd    schedule 22.10.2010
comment
Добавление модуля в предложение uses в каждом модуле в нескольких проектах слишком сложно?   -  person Andreas Rejbrand    schedule 22.10.2010
comment
@Андреас Рейбранд: Да. Если вы не можете принять мой вопрос как действительный: террорист взял в заложники мою жену и убьет ее, если я не смогу разделить TClick и TClack на отдельные единицы, не нарушая существующий код.   -  person Ian Boyd    schedule 24.10.2010


Ответы (1)


Напишите единицу:

unit Tappet;

interface

type
   TSolution = (solTransmission, solBrakes, solGremlins);

   TTappetBrother = class(TObject)
   public
      function GetSolution: TSolution; virtual; abstract;
   end;

implementation

end.

и используйте его в блоках Click и Clack. Затем напишите модуль CarTalk, чтобы он использовал все три, и экспортируйте необходимые типы в его интерфейс. Циклические ссылки не нужны.

person Muhammad Alkarouri    schedule 21.10.2010
comment
Это решение, я думаю. Я предполагаю, что под экспортом необходимых типов вы имеете в виду TClick = class(Click.TClick); ? - person Andreas Rejbrand; 22.10.2010
comment
Более менее. Вам не нужно ключевое слово class. Это просто псевдоним, как это сделано в вопросе. - person Muhammad Alkarouri; 22.10.2010
comment
@Ian Boyd: Как и VCL. Например, TPoint определяется в Types.pas (которое вы редко видите в своем предложении uses), но в Windows.pas (которое почти всегда находится в этом предложении) вы экспортируете его: type TPoint = Types.TPoint; (И, да, const работает как type в этом отношении. ) - person Andreas Rejbrand; 24.10.2010