E2015运算符不适用于此操作数类型(Delphi 10.2)

时间:2019-06-28 12:28:48

标签: delphi generics

就像Java Collection接口定义一样,我想创建一个列表类型,其中addItems / removeItems获得一个验证器参数以过滤添加/删除之前的项目。 十分必要的代码段:

IListItemValidator<T> = interface
  ['{79E22756-9EC5-40C5-A958-0AA04F6F1A79}']
  function validateItem( item_ : T ) : boolean;
end;

IList<T> = interface
  ['{DC051351-D7B7-48BB-984E-A0D9978A02C1}']
  function getCount : cardinal;
  function itemAt( ndx_ : cardinal ) : T;
  function addItems( list_ : ILIst<T>; validator_ : IListItemValidator<T> = NIL );
end;

TList<T> = class ( TInterfacedObject, IList<T> )
  private
    fCount : cardinal;
    fItems : TArray<T>;
  public
    function getCount : cardinal;
    function getItemAt( ndx_ : cardinal ) : T;
    function addItems( list_ : ILIst<T>; validator_ : IListItemValidator<T> = NIL );

function TList<T>.getCount : cardinal;
begin
  result := fCount;
end;

function TList<T>.getItemAt( ndx_ : cardinal ) : T;
begin
  if ( ndx_ < fCount ) then
    result := fItems[ndx_]
  else
    ;//raise...
end;

function TList<T>.addItems( list_ : ILIst<T>; validator_ : IListItemValidator<T> = NIL );
var
  i : integer;
  item : T;
begin
  if ( list_ <> NIL ) then
    for i := 0 to list_.getCount-1 do
    begin
      item := list_.getItemAt( i );
      if ( ( validator_ = NIL ) or validator_.validateItem( item ) ) then
        //addItem
      else
        result := -1;
    end
  else
    ;//raise...
end;

如果要添加值大于4的项目,应该如何定义TListItemValidator? (例如) 匿名函数参数化的重载addItems / removeItems方法工作正常,但是如何创建基于通用接口的解决方案?

没有一个版本可以编译:

第一个(很明显。T与System.Integer不兼容)

TListItemValidator<T> = class ( TInterfacedObject, IListItemValidator<T> )
  public
    function validateItem( item_ : T ) : boolean;
end;

function TListItemValidator<T>.validateItem( item_ : T ) : boolean;
begin
  result := item_ > 5;
end;

第二个(我尝试直接使用整数):

TListItemValidator<integer> = class ( TInterfacedObject, IListItemValidator<integer> )
  public
    function validateItem( item_ : integer ) : boolean;
end;

function TListItemValidator<integer>.validateItem( item_ : integer ) : boolean;
begin
  result := item_ > 5;
end;

编译错误: E2015 Operator not applicable to this operand type

我理解原因:'TListItemValidator'中的'integer'就像第一个示例中的'T'一样,只是类型占位符。但是如何为整数值创建一个有效的验证器?

2 个答案:

答案 0 :(得分:3)

您的两个变体实际上含义相同:

TListItemValidator<T> = class ( TInterfacedObject, IListItemValidator<T> )
  public
    function validateItem( item_ : T ) : boolean;
end;

TListItemValidator<integer> = class ( TInterfacedObject, IListItemValidator<integer> )
  public
    function validateItem( item_ : integer ) : boolean;
end;

它们都是通用类型。唯一的区别是修饰,即通用参数的名称。您可能已经为通用参数指定了名称integer,但是在这种情况下,这只是一个名称。

您需要的是一个实现IListItemValidator<integer>的具体类。像这样:

type
  TIntegerListItemValidator = class ( TInterfacedObject, IListItemValidator<integer> )  
    function validateItem( item_ : integer ) : boolean;
  end;

function TIntegerListItemValidator.validateItem( item_ : integer ) : boolean;
begin
  result := item_ > 4;
end;

答案 1 :(得分:2)

好。我在David发表评论的同时找到了解决方案。 我修改了验证器定义:

IListItemValidator = interface
  [...]
  function validateItem( const item_ ) : boolean;
end;

TIntegerListItemValidator = class ( TInterfacedObject, IListItemValidator )
  function validateItem( const item_ ) : boolean;
end;

function TIntegerListItemValidator.validateItem( const item_ ) : boolean;
begin
  result := integer( item_ ) > 4;
end;