Reputation: 816
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
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
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