Delphi 中的通用助手 类

Generic helper classes in Delphi

我有一对 classes,A 和 B,它们必须相互引用。这意味着A的接口uses子句必须提到B的单位,B的接口uses子句必须提到A的单位。这是Delphi中的循环引用,是不允许的。我正在使用 here 找到的方法解决循环问题。基本上,A 对 B 的引用按预期存在,但 B 对 A 的引用被降级为 TObject 引用,并且 B 使用助手 class 将对 A 的引用转换为正确的类型。以下是用于说明的代码片段:

unit A;

interface

uses
    B;

type
    TA = class(TObject)
    public
        Name: string;
        B: TB;
    end;

implementation

end.

unit B;

interface

type
    TB = class(TObject)
    public
        Name: string;
    protected
        fA: TObject;
    end;

implementation

end.

unit BHelper;

interface

uses
    A,
    B;

type
    TBHelper = class helper for TB
    private
        function GetA: TA;
        procedure SetA(Value: TA);
    public
        property A: TA read GetA write SetA;
    end;

implementation

function TBHelper.GetA: TA;
begin
    Result := TA(fA);
end;

procedure TBHelper.SetA(Value: TA);
begin
    fA := a;
end;

end.

我实际上有几双这样的 classes。有很多 class 帮手,他们都在做同样的事情。所以我试着写一个通用的助手 class 可以参数化来帮助 class 像 B:

unit GenericHelper;

interface

uses
    A,
    B;

type
    TGenericHelper<T1, T2> = class helper for T2  //Error: Type parameters not allowed
    private
        function GetA: T1;
        procedure SetA(Value: T1);
    public
        property A: T1 read GetA write SetA;
    end;

implementation

function TGenericHelper<T1, T2>.GetA: T1;
begin
    Result := T1(fA);  //Error: undeclared parameter fA
end;

procedure TGenericHelper<T1, T2>.SetA(Value: T1);
begin
    fA := a;  //Error: undeclared parameter fA
end;

end.

我的问题是我对泛型 classes 的了解还不够,无法确定这是否可行。我不知道如何解决代码中显示的错误。

有办法吗?

爆料:实际情况比这丰富多了。这些对按层次结构排列,如 A-B-C-D,其中 A 持有对 B 的引用,B 持有对 A 和 C 的引用,C 持有对 B 和 D 的引用,D 持有对 C 的引用。这些是一对多关系,其中 A 实际上持有 B 的列表,每个 B 持有 C 的列表,每个 C 持有 D 的列表。理想的解决方案不会排除这些关系。我也更喜欢每个单元一个 class,而不是将相关的 class 组合成一个单元。

谢谢

这个错误很明显

 TGenericHelper<T1, T2> = class helper for T2  //Error: Type parameters not allowed

你不能像这样使用泛型。原因应该很明显,因为在实例化通用 class(使实现非通用)之前,您的实现试图访问属于特定 class 的变量。

最简单的做法是将 A/B(和 C/D 等)放入一个单元中,然后简单地使用 classes 的前向声明。

unit ABCD;

interface

    TB = class;
    TC = class;
    TD = class;

    TA = class(TObject)
      public
        B: TB;
        C: TC;
    end;

    TB = class(TObject)
       public
         A: TA;
    end;

    TC = class(TObject)
      public
        B : TB;
        D : TD;
    end;

    TD = class(TObject)
      public
        A: TA;
        C: TC;
    end;

implementation

end.