我有两个单元,每个单元中有一个 class,它们需要彼此才能发挥作用。如何避免循环引用?

I have two units and a class in each unit that need each other to function. How do I avoid a circular reference?

我有 2 个 类、ClassAClassB,每个都在自己独立的单元中,UnitAUnitB

UnitA 使用 UnitB。这允许 ClassA 调用 ClassB 的构造函数。然而,部分 ClassB's 功能需要使用 ClassA's 方法。我不能让 UnitB 使用 UnitA,否则会导致循环引用。我有什么选择可以让 ClassBUnitB 访问 ClassA's 方法?

这在很大程度上取决于两个 classes 需要如何相互使用。如果一个 class 在实现中使用了另一个,而不是接口,那么您可以将 uses 子句中的该单元从 interface 部分向下移动到 implementation 部分。

这两种方法都可行:

UnitA;

interface

uses
  Classes, UnitB;

type
  TClassA = class(TObject)
  end;

...

.

UnitB;

interface

uses
  Classes;

type
  TClassB = class(TObject)
  end;

implementation

uses
  UnitA;

...

然而,如果你的两个 classes 的接口相互依赖,那么你别无选择,只能将两个 classes 放在同一个单元中(并使用前向声明)。

UnitA;

interface

uses
  Classes;

type
  TClassA = class;
  TClassB = class;


  TClassA = class(TObject)
  end;

  TClassB = class(TObject)
  end;

...

在极少数情况下,您甚至可以将整个 class 定义向下移动到 implementation。如果您需要在其他地方实际使用 class,那将没有用。

UnitB;

interface

implementation

uses
  Classes, UnitA;

type
  TClassB = class(TObject)
  end;

...

根据复杂性,将共同共享的代码放在一个单独的单元中也是常见的做法。例如常量、记录数组类型、全局变量等。这个公共单元不得使用任何其他这些单元。

为了稍微扩展之前的答案,另一种可能性(虽然肯定不太可读)是指一个祖先,它们都可以访问(在极端情况下是 TObject),然后在实现阶段进行转换。所以

interface

TClassA = class
...
fRefToClassB : TObject;  // internal ref
...
procedure UsingBRef( pVar : TObject );
...
end;

implementation

procedure TClassA.UsingClassB
begin
  with fRefToClass as TClassB do
...
end;

procedure TClassB.UsingBRef( pVar : TObject );
begin
  with pVar as TClassB do
...
end;

显然,同一个主题有很多变体,您实施的会比这更好。我要再次强调以前的解决方案更好,但是当其他所有方法都失败时,这提供了一个出路。

如果您有 Class 和 Class B,并且都使用 ClassA 中的方法,那么您可能希望将这些方法从 ClassA 重构到它们的单元中(如果您愿意,还可以 class)。