`
lovnet
  • 浏览: 6705521 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
文章分类
社区版块
存档分类
最新评论

使用ClassHelper\record helper 给类“打补丁”

阅读更多

有些时候,我们需要在现有类的基础上,给类添加一些东西
并且在类中protected区分的方法,成员是无法在单元外访问的,如果要调用它们该怎么办呢?
于是就有了以下三种方法

1. 继承该类
2. 直接覆写该类
3. 使用Class Helper

对于第一种方法,大家都很熟悉,我就不多说了,第二种方法的实现:

TControl =class(Controls.TControl)
private
FText: WideString;
published
propertyText: WideStringreadFTextwriteFText;
end;


而第三种,就是我在本文中要说的,利用ClassHelper来实现对类的扩展,也可以称之为,给类“打补丁”

具体的操作方式如下,假设有一个很简单的类:
type
TTestClass =class
private
FInfo:string;
protected
procedureDoTest;
public
functionDoAdd(a,b: integer):string;
public
propertyInfo:string readFInfowriteFInfo;
end;

我现在想给它添加一个DoMinus方法,于是就有了这个Class Helper

type
TTestClassHelper =class helper forTTestClass
public
functionDoMinus(a,b: integer):string;
end;

可以看到,只是很简单的声明一个class helper,然后在里面添加内容。
这样做的好处是,原本的类代码不会被改动,只是扩展
在class helper内,可以访问到基类的protected, public, published区分符下的成员,属性和方法,但是不能访问private下的。

经过class helper的补丁后,我们就可以在基类的实例下调用添加的新方法了
var
t:TTestClass;
begin
t:=TTestClass.Create;
t.DoAdd(1,2);
t.DoMinus(2,1);
end;

这只是一个很小的例子,以前我曾经见过把class helper用得非常复杂的。它对于代码有着相当强的隐蔽性
例如:
type
TTestClass =class
protected
FA, FB, FC:string;
public
end;

type
TTestClassHelper =class helper forTTestClass
public
procedureDo1;
procedureDo2;
......
end;

这样的代码看着真能让人头疼,按着Ctrl点类名只能看到一个空的类,没有一个方法。
实现的代码全都放在了class helper里,并且class helper也不是写在pas里,是拆分后写在inc里了

总结
class helper对于简单的对类打补丁而言,是比较有用的,毕竟写一个class helper和继承一个类差不多,而且class helper不会对基类造成影响,也不用担心一个不小心就把基类的东西override错了
但是class helper并不适合用在较大规模的类复写中,特别是用class helper来实现半开源的产品,将非常不利于代码的维护(如果是商业手段则不在此列),此时就需要较为详尽的文档来标识class helper以及其所指的类。

当初Delphi 2007为了兼容D2006编译的单元,才想到了用Class Helper。不过Class Helper/Record Helper只适合作为”补丁“,一般不要放到常规的设计里面。


使用了Record Helper来扩展TGuid结构,很方便。

type
TGuidHelper = record helper for TGUID
private
class function GetEmpty: TGUID; static;
public
class function Create(const g: string): TGUID; overload; static;
class function NewGuid: TGUID; static;
function Equals(const guid: TGUID): Boolean;
function ToString: string;
class property Empty: TGUID read GetEmpty;
end;

http://blog.sina.com.cn/s/blog_6016bdc80100dhbh.html~type=v5_one&label=rela_prevarticle?1290186141

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics