扩展 delphi 泛型 以实现类似lambda功能 , C#中的any count first last 等扩展方法
在C#中对泛型的扩展,输入参数是泛型本身的内容,返回值则是bool.基于这一点,开始构造在delphi下如何实现.
首先 1.delphi 是支持匿名函数的其语法为: 名称 = reference to 函数类型定义 例如: TFun = reference to function(const num: Integer): Integer;
2.对泛型的扩展的语法如下: TList<T> = class(Generics.Collections.TList<T>) public *********** end;
有了如上的两点,便可以实现我们想要的功能了.其主要思路为: 为泛型扩展的any count方法添加类型为"Ibool接口"的参数.Ibool接口类型的参数就是泛型本身的内容,返回值则是Boolean
在调用这些扩展时,只需要构造出一个支持Ibool接口的对像就可以了.
对于Ibool接口,支持Ibool接口的对像,any等扩展方法之间的关系请细细考虑.对高手来说很简单了吧,就是一个简单的设计模式.
主要代码,注释如下: unit UCryHelper;
interface uses Generics.Collections; type IBool<T>=interface //这就是Ibool接口的定义 function Compare(Right: T): Boolean; end;
TBoolsion<T> = reference to function( Right: T): Boolean;//匿名函数 因为是对泛型的支持所以要有那个"T". 这个的类型与Ibool接口方法的类型是一样的,定义成这样后,用这个匿名函数连接你写的实际的函数体和泛型
TBool<T>=class(TInterfacedObject, IBool<T>) //这是支持IBool接口的对像,这是虚函数,实际的执行者是下边的定义. public class function Construct(const EqualityComparison: TBoolsion<T>): IBool<T>; function Compare(Right: T): Boolean;virtual; abstract; end;
TDelegatedBool<T> = class(TBool<T>) //前三个类型是必备的类型,这行则是实际的执行者. private FEquals: TBoolsion<T>; public constructor Create(const AEquals: TBoolsion<T>); function Compare(Right: T): Boolean; overload; override; end;
TList<T> = class(Generics.Collections.TList<T>) //这是对泛型的扩展,不用多说了. public type TDynArray = array of T; function ToArray: TDynArray; function Any(const AComparer: IBool<T>):Boolean; //扩展方法Any的参数为IBool<T>返回值是Boolean end; implementation
function TList<T>.Any(const AComparer: IBool<T>): Boolean; var one:T; begin Result:=False; for one in Self do begin if AComparer.Compare(one) then begin Result:=True; Exit; end; end; end;
function TList<T>.ToArray: TDynArray; var I: Integer; begin SetLength(Result, self.Count); for I := 0 to Self.Count - 1 do begin Result[I] := Self[I]; end; end; { TBool<T> }
class function TBool<T>.Construct(const EqualityComparison: TBoolsion<T>): IBool<T>; begin Result:= TDelegatedBool<T>.Create(EqualityComparison); end;
{ TDelegatedBool<T> }
function TDelegatedBool<T>.Compare(Right: T): Boolean; begin Result := FEquals(Right); end;
constructor TDelegatedBool<T>.Create(const AEquals: TBoolsion<T>); begin FEquals:= AEquals; end; end.
最终的调用就是这样用了.先use UCryHelper 然后
procedure TfrmSampleInput.btnQuitClick(Sender: TObject); var listint:TList<Integer>; boolCal:IBool<Integer>; begin inherited; listint:=TList<Integer>.Create; listint.Add(1); listint.Add(33); listint.Add(3); listint.Add(4);
boolCal:=TBool<Integer>.Construct( function ( Avalue: integer): Boolean begin result := Avalue=listint.Count; end ); if(listint.Any(boolCal)) then ShowMessage('OOKK!!'); {如果想把boolCal:IBool<Integer>;的声明省了,这样用也是可以的,怎么样?和C#里的any方法差不多吧. if listint.Any(Tbool<Integer>.Construct(function(Avalue:Integer):Boolean begin result := Avalue=listint.Count; end )) then ShowMessage('OOKK!!');} listint.Free; end;
以上就是一个扩展any的实现,有了这个any,再扩展count first last等其它方法还不就简单了?快试试吧.
|
请发表评论