Два класса с двумя циклическими ссылками

У меня есть два разных класса, созданных в двух разных модулях, как мне создать циклические ссылки? в Delphi (классы в разных единицах измерения)

раздел 1:

Uses unit2;

type Ta = class(tobject)
   public
       b:Tb;
end;

Модуль 2:

type Tb = class(tobject)
   public
       a:Ta;
end;

person user558126    schedule 03.01.2012    source источник


Ответы (2)


Действительно можно обойти круговую ссылку на единицу измерения, используя class helpers.

Добавив общий UnitClassHelper, включая помощники классов для Ta и Tb, это можно решить следующим образом:

unit Unit1;

interface

type Ta = class(tobject)
   public
       b : TObject;
end;

implementation

uses UnitClassHelper;

-

unit Unit2;

interface

type Tb = class(tobject)
   public
       a : TObject;
end;

implementation

uses UnitClassHelper;

-

unit UnitClassHelper;

interface

uses Unit1,Unit2;

Type TaHelper = Class Helper for Ta
   private
     function GetTb : Tb;
     procedure SetTb( obj : Tb);
   public
     property B : Tb read GetTb write SetTb;
 End;

Type TbHelper = Class Helper for Tb
       private
         function GetTa : Ta;
         procedure SetTa( obj : Ta);
       public
         property A : Ta read GetTa write SetTa;
     End;

implementation

function TaHelper.GetTb: Tb;
begin
  Result:= Self.B;
end;

procedure TaHelper.SetTb(obj: Tb);
begin
  Self.B:= obj;
end;

function TbHelper.GetTa: Ta;
begin
  Result:= Self.A;
end;

procedure TbHelper.SetTa(obj: Ta);
begin
  Self.A:= obj;
end;

end.

-

program Test;

uses
  Unit1 in 'Unit1.pas',
  Unit2 in 'Unit2.pas',
  UnitClassHelper in 'UnitClassHelper.pas';

var
  AObj : Ta;
  BObj : Tb;

begin
  AObj:= Ta.Create;
  BObj:= Tb.Create;
  try
    AObj.B:= BObj;
    BObj.A:= AOBj;
    // Do something

  finally
    AObj.Free;
    BObj.Free;
  end;
end.

См. также отличный обзор class helpers: решение-круговых-ссылок-юнитов-с-помощниками-классами

person LU RD    schedule 05.01.2012

Я полагаю, вы имеете в виду, как мне избавиться от них!

Поместите их оба в один файл, и, учитывая вашу структуру, вы также можете получить один ответ.

type tb = class;

type Ta = class(TObject)
   public
       b:Tb;
end;

type Tb = class(TObject)
   public
       a:Ta;
end;

Другие способы зависят от ситуации, например, можете ли вы абстрагироваться от класса, который может владеть Ta или Tb, или класс может принадлежать Ta или Tb...

Однако я бы порекомендовал вам взглянуть на интерфейсы....

Хорошо, два разных файла

Ну нет, три...

Unit3;
    type tc = class(TObject)
        public c:Tc;
    end;

Unit1;
    type Ta = class(TObject)
       public
           b:Tc;
    end;

Unit2;
    type Tb = class(TObject)
       public
           a:Tc;
    end;

Or

Unit3;
type Ic = interface; end;

Unit1;
    type Ta = class(TObject)
       public
           b:Ic;
    end;

Unit2;    
    type Tb = class(TObject)
       public
           a:Ic;
    end;

Найдите общий бит, выведите его в третьем блоке, чтобы два других использовали его в основном. Помимо всего прочего, это даст вам лучший дизайн.

person Tony Hopkinson    schedule 03.01.2012
comment
Я хочу иметь оба в двух разных файлах. - person user558126; 03.01.2012
comment
@user Мы все этого хотим, но это невозможно. Разумное использование интерфейсов — еще один вариант. - person David Heffernan; 04.01.2012
comment
Я хотел два разных класса - person user558126; 04.01.2012
comment
У вас может быть два разных класса. Но если им нужно иметь ссылки друг на друга, они должны быть в одном и том же блоке. - person David Heffernan; 04.01.2012
comment
Ваш первый пример не будет компилироваться. Предварительное объявление класса должно находиться в том же блоке типов, что и фактическое объявление типа. Таким образом, это тип ‹cr› Ta=class; ‹cr› Tb=класс [...] конец; ‹cr› Ta=класс [...] конец; ‹cr› без дополнительных ключевых слов типа. (извините, комментарии не позволяют перевод строки). - person dummzeuch; 09.02.2017