在 class 声明中使用自己的 class 作为类型参数约束

Using own class as a type parameter constraint in class declaration

我在 Delphi XE8 中有一个 class 的以下声明:

TestClass = class;
TestClass = class
  function test<T: TestClass>(supplier: TFunc<T>): T; // Compiler error
end;

这会引发以下编译器错误:

E2086 Type 'TestClass' is not yet completely defined

当我将另一个 class 添加到组合中并将其用作约束时,它工作正常:

AnotherTestClass = class
end;

TestClass = class;
TestClass = class
  function test<T: AnotherTestClass>(supplier: TFunc<T>): T; // No Error
end;

我怀疑问题是前向类型声明还没有告诉 Delphi 关于 TestClass 类型的足够信息。这可能更明显,因为以下解决该问题的尝试会在不同的行上抛出完全相同的编译器错误:

TestClass = class;
AnotherTestClass = class (TestClass) // Compiler Error
end;
TestClass = class
  function test<T: AnotherTestClass>(supplier: TFunc<T>): T;
end;

我是不是做错了什么,如果没有,有没有办法解决这个问题?

你没有做错任何事。你正在尝试的应该是可能的,但在我看来,编译器是有缺陷的。如果不完全改变设计,就没有可行的方法来解决这个问题。解决此问题的一种方法是在运行时强制执行约束。但是,在我看来,这算是彻底改变了设计。

请注意,在 .net 中,您尝试做的事情是完全可能的:

class MyClass
{
    private static T test<T>(Func<T> arg) where T : MyClass
    {
        return null;
    }
}

Delphi 泛型功能基于 .net 泛型,我怀疑您面临的问题归结为 Delphi 开发人员的疏忽。

您应该提交错误报告/功能请求。

更新 1

LU RD 建议更好的解决方法。使用 class 助手:

type
  TestClass = class
  end;

  TestClassHelper = class helper for TestClass
    function test<T: TestClass>(supplier: TFunc<T>): T;
  end;

这将允许您在编译时测试约束。但是,它确实会强制您在不整洁的函数之外定义方法,并且会阻止您将 class 助手用于任何其他目的。因此,在我看来,您仍然应该提交错误报告/功能请求。

更新 2

错误报告:RSP-13348