简体   繁体   English

类型X的参数必须支持接口Y.

[英]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.

相关问题 TYPESCRIPT :类型“typeof X”的参数不能分配给类型为“Y”的带有扩展的参数 - TYPESCRIPT : Argument of type 'typeof X' is not assignable to parameter of type 'Y' with extends 可访问性不一致:参数类型“x”比方法“y”更难访问 - Inconsistent accessibility: parameter type 'x' is less accessible than method 'y' PHPDoc的参数必须是实现接口的特定类 - PHPDoc for a parameter that must be a specific class implementing an interface 通用接口方法参数的实际类型 - Actual type of generic interface method parameter 接收继承它的类类型的参数的接口方法 - Interface method that receives a parameter of type of class that inherited it 如何解决类型依赖? (X 使用未定义的 class Y) - How to unravel type dependency? (X uses undefined class Y) 如果一个类正在使用接口,那么它必须 - If a class is using an interface, it must &#39;未声明的标识符&#39;/&#39;标识符“x”未定义&#39;/&#39;class Y没有成员“x”&#39;使用结构类型指针 - 'Undeclared identifier' / 'identifier "x" undefined' / 'class Y has no member "x" ' working with struct-type pointers File类型的对象必须支持迭代协议,并在文件的各行中进行迭代 - Objects of type File must support the iteration protocol, and iterates through the lines of the file C#:如何设计泛型类,以便type参数必须继承某个类? - C#: How to design a generic class so that the type parameter must inherit a certain class?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM