泛型、接口和继承的问题

6
以下示例给我带来了这个错误:
[DCC Error] Unit2.pas(54): E2010 不兼容的类型:'IBar' 和 'Unit2.TFoo<Unit2.IBar>' 我认为问题出在Self.Create周围,因为我经过多次尝试编译它后,我不小心输入了FFoo := TBar(Self).Create;然后它就编译并正常工作了。
我正在使用Delphi XE。
IFoo = interface
end;

TFoo<T: IInterface> = class(TInterfacedObject, IFoo)
private class var
  FFoo: T;
public class
  function Instance: T;
end;

IBar = interface(IFoo)
end;

TBar = class(TFoo<IBar>, IBar)
end;

class function TFoo<T>.Instance: T;
begin
  if not Assigned(FFoo) then
  begin
    FFoo := Self.Create;
  end;
  Result := FFoo;
end;

4
错误提示告诉你一个行号。也许你可以准确地指出是哪一行,而不是猜测问题可能在哪里? - Anon.
1
错误在“end”的下一行。 - RjK
强制转换TBar(Self).Create是不必要的,因为您不确定Self是否为TBar 并且它会破坏泛型的概念(不能用于另一个类)! - TridenT
1
这里不支持行号真是太遗憾了。 - Free Consulting
2017年和东京.2仍然是一样的。 - JensG
2个回答

4
问题出在TBar声明的这一行:
FFoo := Self.Create;

为了理解,我们来解释一下代码后面的类型[类似于这样的注释]:
FFoo:[IBar] := Self:[TFoo(IBar)].Create():[TFoo<IBar>]

因此,总结一下,我们有:[IBar] := [TFoo<IBar>]
这些类型是否兼容?
一个[TFoo]只实现了IFoo接口,没有像你的代码中所声明的IBar

TFoo<T: IInterface> = class(TInterfacedObject, IFoo)

这是编译错误!
更新:解决方案 1
要解决问题:更改TBar声明。

TBar = class(TFoo<IFoo>, IBar)
end;

更新:解决方案2
FFoo := Self.Create 替换为

FFoo := Self.Create.Instance;

所以它可以工作!


这不是解决方案,因为函数Instance的结果类型将是IFoo而不是IBar。 - RjK
@RjK:我已经用解决方案2更新了我的帖子。我认为这就是我们正在寻找的! - TridenT
更新:方案2 -> 这将导致堆栈溢出。 - RjK

1

你的 TFoo 没有实现 T 接口。这就是为什么 FFoo 和 TFoo 实例不兼容的原因。如果你想将 TFoo 的实例分配给 FFoo,你需要进行硬转换。


你是指在Instance函数中这段代码吗:Result := T(FFoo); 它可以编译通过,但是当我运行它时,在函数的最后一个end处出现了AV错误。(地址00000001处的访问冲突。读取地址00000001。) - RjK

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接