【问题标题】:Using own class as a type parameter constraint in class declaration在类声明中使用自己的类作为类型参数约束
【发布时间】:2016-04-09 05:33:18
【问题描述】:

我在 Delphi XE8 中有以下类的声明:

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

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

E2086 Type 'TestClass' is not yet completely defined

当我添加另一个类并将其用作约束时,它可以正常工作:

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;

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

【问题讨论】:

  • 看来这是编译器的bug所以我提交了bug report here
  • 当然是代码“TestClass = class;AnotherTestClass = class (TestClass) //编译器错误结束;”应该会产生所示的错误,因为 Delphi 是单通道编译器。但我看不出为什么同样适用于您尝试创建的构造。当时有足够的信息使定义有效。
  • @Dsm 同意,但由于编译器错误是相同的,我认为这是出问题的提示。但是这确实带来了一个问题,如果我想要两个互相使用作为类型参数约束的类怎么办?
  • 我认为同样的问题适用于您的两个类,它们相互使用作为类型参数约束。显然这两个类需要在相同的单元和相同的类型块中,就像类相互引用一样,但我想你会遇到同样的问题。就像你的例子一样,我认为编译器没有理由不允许它。

标签: delphi generics forward-declaration delphi-xe8 type-constraints


【解决方案1】:

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

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

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

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

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

更新 1

LU RD 提出了一个更好的解决方法。使用类助手:

type
  TestClass = class
  end;

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

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

更新 2

错误报告:RSP-13348

【讨论】:

  • 将函数移动到类助手编译:`TestClassHelper = TestClass 函数 test(supplier: TFunc): T;结尾; `.
  • @LURD 很好,这实际上是一个可行的解决方法。类的行为和 API 应该与预期的相同,对吧?尽管如此,这仍然是编译器的一个重大疏忽,所以我仍然会提交一个错误报告。
  • 请在此处发布您的错误报告的链接。如果人们希望泛型功能更加正交和完整,他们可能会投票支持它。
  • @WarrenP 我就在上面 :) Here's the bug report。请注意,我以前从未写过功能请求。
  • 我认为更好的解决方法是使用抽象基类作为约束。这将使模拟 TestClass 变得更容易。添加构成类型签名的任何虚拟抽象函数。
猜你喜欢
  • 2012-09-28
  • 1970-01-01
  • 1970-01-01
  • 2017-04-11
  • 2019-03-31
  • 1970-01-01
  • 2019-03-21
  • 1970-01-01
相关资源
最近更新 更多