SOLID Developper
SOLID Developper

Reputation: 816

E2015 Operator not applicable to this operand type (Delphi 10.2)

Like in the Java Collection interface definition, I want to create a list type, which addItems/removeItems get a validator parameter to filter the items before addition/deletion. The very necessary code snippet:

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;

How should I define a TListItemValidator if I want to add items with value larger then 4? (for example) The anonymous function parameterized overloaded addItems/removeItems methods just work fine but how can I create the generic interface based solution?

No one variation compiles:

The first one (it is clear. the T is not compatible with 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;

The second one (i tried to use integer directly):

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;

The compilation error: E2015 Operator not applicable to this operand type

I understand the reason : the 'integer' in the 'TListItemValidator'is just like 'T' in the first example, just the type placeholder. But how could I create a working validator for integer values?

Upvotes: 2

Views: 1079

Answers (2)

David Heffernan
David Heffernan

Reputation: 612954

Your two variants are in fact identical in meaning:

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;

They are both generic types. The only difference is cosmetic, namely the name of the generic parameter. You might have given the generic parameter the name integer, but that is just a name, in this context.

What you need is a concrete class that implements IListItemValidator<integer>. Something like this:

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

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

Upvotes: 3

SOLID Developper
SOLID Developper

Reputation: 816

OK. I found the solution in the same time when David send his comment. I modified the validator definition:

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;

Upvotes: 2

Related Questions