[英]Parameter of type X must support interface Y
I have a setup like so : 我有这样的设置:
IBuilder = interface(IInvokable)
end;
IBuilder<T: IBuilder; TOut : TWinControl> = interface(IInvokable)
end;
TBuilder<T: IBuilder; TOut : TWinControl> = class(TInterfacedObject, IBuilder, IBuilder<T, TOut>)
end;
TBuilder = class(TBuilder<TBuilder, TWinControl>)
end;
This kind of structure allows me to build a sugar syntax like so : 这种结构允许我像这样构建一个糖语法:
TBuilder<T : IBuilder; TOut : TWinControl> = class(TInterfacedObject, IBuilder, IBuilder<T, TOut>)
function Output : TOut;
function Name(aName : string) : T;
function Left(aLeft : Integer) : T;
function Top(aTop : Integer) : T;
end;
// ... later
TBuilder.Create().Left(10).Top(5).Name('ABC'); // Nice one liner
The problem is that I get a compilation error, saying that 问题是我得到了编译错误,这样说
E2514 The type parameter TBuilder must support interface 'IBuilder'.
This is probably due to the typed constraint T: IBuilder
present on the interface, even though TBuilder does support IBuilder (trough it's ancestor). 这可能是由于接口上存在类型约束
T: IBuilder
,即使TBuilder确实支持IBuilder(通过它的祖先)。
Can anyone please direct me on how to get around this? 任何人都可以指导我如何解决这个问题?
Though, I cannot use TBuilder = class(TBuilder<IBuilder, TObject>)
虽然,我不能使用
TBuilder = class(TBuilder<IBuilder, TObject>)
This can't be done. 这是不可能做到的。 You're essentially trying to do this :
你基本上是想这样做:
IBar = interface(IInterface) end;
TFoo<T : IBar> = class(TObject, IBar) end;
TBar = TFoo<TBar>;
Which generates error 哪会产生错误
E2086 Type 'TBar' is not yet completely defined
E2086型'TBar'尚未完全定义
Without the interface dependence you can write this as 如果没有接口依赖性,您可以将其写为
TBar = class(TFoo<TBar>) end;
making it a true descendent and not just an alias. 使它成为一个真正的后代,而不仅仅是一个别名。 This could normally resolve the type, but the interface dependence is forcing the compiler to ask the question : Does
TBar
support IBar
? 这通常可以解析类型,但是接口依赖性迫使编译器提出问题:
TBar
是否支持IBar
?
If you think about it, this works out as : 如果你考虑一下,这就是:
TBar = TFoo<TBar> {TBar support IBar?}
|
TBar = TFoo<TBar>... {ok, TBar support IBar?}
|
TBar = TFoo<TBar> {ok, TBar support IBar?}
|
{...turtles all the way down}
You're asking the compiler to solve an infinite recursion problem. 您要求编译器解决无限递归问题。 It cannot do this.
它无法做到这一点。
You can fix this by changing the return type of your methods, and excluding the recursive type parameter. 您可以通过更改方法的返回类型并排除递归类型参数来解决此问题。
interface
type
//IBuilder = interface(IInvokable)
//end; //I don't think you need this
IBuilder<TOut : TWinControl> = interface(IInvokable)
function Output : TOut;
function Name(const aName : string) : IBuilder<TOut>;
function Left(aLeft : Integer) : IBuilder<TOut>;
function Top(aTop : Integer) : IBuilder<TOut>;
end;
TFactory<TOut: TWinControl> = record
class function New: IBuilder<TOut>; static;
end;
implementation
type
//Put the actual class in the implementation
TBuilder<TOut : TWinControl> = class(TInterfacedObject, IBuilder<TOut>)
//see interface
end;
You normally use this like so: 你通常这样使用它:
var
MyButton: IBuilder<TButton>;
begin
MyButton:= TFactory<TButton>.New.Left(10).Top(5).Name('ABC');
If you're using interface then you should never work with the class, always interact with the interface exclusively. 如果您正在使用接口,那么您永远不应该使用该类,始终只与该接口进行交互。 By moving the class definition in the implementation you enforce this.
通过在实现中移动类定义,您可以强制执行此操作。 To compensate you add a factory method in the interface.
为了补偿您在界面中添加工厂方法。
In this case it has to be a record, because you cannot (yet) have generic stand-alone methods. 在这种情况下,它必须是一个记录,因为你不能(还)拥有通用的独立方法。
class function TFactory<TOut>.New: IBuilder<TOut>;
begin
Result:= TBuilder<TOut>.Create;
end;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.