记得我是在delphi2005里面看到Record可以和Class一样定义方法(Function、Procedure)的,最近几年不像年轻时太爱看语言新特性了。Delphi XE2将正则表达式加入到了系统,成为体系的一部分 System.RegularExpressions,但是它表现出来的是TRegEx记录,对,是记录,不是类,也许是为了效率考虑,之后也从没有看过实现,虽然我们大家都知道Delhpi是最大的开源软件(从1~现在26既 DX10.3所有的代码都是公开的)!
最近想将一小片lazarus代码转回Delhpi,由于Lazarus系统自带正则表达式目前主推的是 RegExpr 类(很早就开源),将其转换到TRegEx记录,在实现上确实有改动较大举个列子,至少没有释放!
function FindOutRex(const aString: string; const aRex: string): string; var {$IFDEF fpc} RegEx: TRegExpr; {$ELSE} RegEx: TRegEx; vM:TMatch; {$ENDIF} begin Result := \'\'; // 表示没有匹配的,Indicates that there is no match. {$IFDEF fpc} try RegEx := TRegExpr.Create; RegEx.Expression := aRex; if RegEx.Exec(aString) then Result := RegEx.Match[0]; finally RegEx.Free; end; {$else} RegEx:=TRegEx.Create(aRex); vM:=RegEx.Match(aString); if vM.Success then Result := vM.Value; {$ENDIF} end;
如果代码中大量使用正则表达式,由于一个是类一个是记录,一个存在建立、释放,一个只用形式上的建立也就是初始化,这这样更改量太大了。
进一步跟踪发现Delphi在实现这个记录时其实用还是调用System.RegularExpressionsCore的类,也就是我们我们很早就用过的TPerlRegEx类,其实这个和lazarus里面就是一样一样的,类名现在稍有不同而已,好!现在关于这个项目中正则表达式类快速转换的问题可以很快解决了,我直接用继承类即可。
但再看看Delphi代码你应该会想到,Delphi实现类的记录化,类是要实例化为对象,然后非接口的对象要可视化释放!这个在转化后的记录是怎么释放资源的呢!
原来他是利用了”通告”,还是利用的接口特性——FNotifier: IInterface;!
其代码定义在实现段
TScopeExitNotifier = class(TInterfacedObject) private FRegEx: TPerlRegEx; public constructor Create(const ARegEx: TPerlRegEx); destructor Destroy; override; property RegEx: TPerlRegEx read FRegEx; end; .. // Helper to extract RegEx object function GetRegEx(const Notifier: IInterface): TPerlRegEx; inline; begin Result := TScopeExitNotifier(Notifier).RegEx; end; { TScopeExitNotifier} constructor TScopeExitNotifier.Create(const ARegEx: TPerlRegEx); begin FRegEx := ARegEx; end; destructor TScopeExitNotifier.Destroy; begin FRegEx.Free; // 在这里释放 ,This is where the release is inherited; end; .. { TRegEx } constructor TRegEx.Create(const Pattern: string; Options: TRegExOptions); begin FOptions := Options; FRegEx := TPerlRegEx.Create; FRegEx.Options := RegExOptionsToPCREOptions(FOptions); if (roNotEmpty in Options) then FRegEx.State := [preNotEmpty]; FRegEx.RegEx := Pattern; FNotifier := TScopeExitNotifier.Create(FRegEx); if (roCompiled in FOptions) then FRegEx.Compile; end;
那么在记录离开作用域将要释放的时候,FNotifier 自然会被nil,利用接口贴特性,这时正则表达类对象资源自然也就释放了。