Delphi里的模板类

 

{Anyway I thought I would take the original idea by Rossen and extend the article to include interfaces as well as classes. The original article dealt with an example of how to create a Collection template and a Vector template. I will show how to create a very simple List template class that manages object pointers and is totally type safe; and then go on to describe the same idea but for the management of interface references.Let’s start by defining the type of object that we want to manage in our List:

我最好认为把Rossen文章里的最初想法扩展到包括接口和类。他的文章里例解了如何创建容器模板和向量模板。我将向你展示如何创始一个非常简单List模板类,它管理对象指针,而且是类型安全的;然后将同样的方法适用于接口引用的管理。
首先,让我们通过定义MyThing类型 ,它将是List里管理的对象。
}
TMyThing = class
  procedure DoIt;
end;


{Simple but effective!
Now in order to create a template we need to create a Delphi unit that is not a Delphi unit; all it should contain is the following:
简单,有效。
现在,为了创建一个模板,我们需要创建一个Delphi unit,但它不是一般的Delphi unit;它只包括如下要素:
 }
_LIST_CLASS_ = class
private
  fItems: TObjectList;
  function GetCount: Integer;
  function GetItem(Idx: Integer): _ITEM_CLASS_;
public
  function Add: _ITEM_CLASS_;
  procedure Remove(Item: _ITEM_CLASS_);
  procedure Insert(Idx: Integer; Item: _ITEM_CLASS_);
  property Count: Integer
  read GetCount;
  property Item[Idx: Integer]: _ITEM_CLASS_
  read GetItem;
end;
{
What we have done here is to define the behaviour of our List without specifying what type of Items we want to manage. _ITEM_CLASS_ is a ‘marker’ for the real type that will be substituted at compile time. _LIST_CLASS_ is a marker for this template type and will also be substituted.
This unit must not have the usual unit header, etc., and should not be added to the Project Manager in the normal way, otherwise Delphi will complain about a badly formed unit.
Having defined the interface for our List class, we should also define a template for the implementation of that class.
在这里,我们要做的是指定要管理的元素类型,来定义List对象的行为。_ITEM_CLASS_ 只是一个标记,对应编译时的实际类型,同样,_LIST_CLASS_ 对应编译时的模板类型。
 }
function _LIST_CLASS_.GetCount: Integer;
begin
  if fItems <> nil then
  Result := fItems.Count
  else
  Result := 0;
end;

function _LIST_CLASS_.GetItem(Idx: Integer): _ITEM_CLASS_;
begin
  if fItems <> nil then
  Result := _ITEM_CLASS_(fItems[Idx])
  else
  Result := nil;
end;

function _LIST_CLASS_.Add: _ITEM_CLASS_;
begin
  if fItems = nil then
  fItems := TObjectList.Create;
  Result := _ITEM_CLASS_.Create;
  fItems.Add(Result);
end;

procedure _LIST_CLASS_.Remove(Item: _ITEM_CLASS_);
begin
  if fItems <> nil then
  fItems.Remove(Item);
  if fItems.Count = 0 then
  begin
  fItems.Free;
  fItems := nil;
  end;
end;

procedure _LIST_CLASS_.Insert(Idx: Integer; Item: _ITEM_CLASS_);
begin
  if fItems = nil then
  fItems := TObjectList.Create;
  fItems.Insert(Idx, Item);
end;

{
Once again this should reside in a separate unit that has nothing else in it but the above code.
Now we come to writing a concrete class that is based on these interface and implementation templates.
再次强调,以上代码只能在一个单独单元内,不能有其他语句!
现在,我们来写一个实现单元,它基于上面的接口和实现模板。
}
uses
  MyThingUnit, Contnrs;

type
  _ITEM_CLASS_ = TMyThing;
  {$I ObjectListTemplateIntf}
  TMyThingList = _LIST_CLASS_;

implementation

  {$I ObjectListTemplateImpl}

end.


//And that really is all there is to it! We start off by declaring _ITEM_CLASS_ as a substitute type for TMyThing and then use the {$Include} directive to in-line the code from the interface template unit. After the template has been included, all you need to do is to declare the real class of the List container as a substitute for the template marker.
//The implementation is even simpler and only requires a {$Include} to successfully compile your first Delphi template _class.
 // 实际如此!我们一开始就把_ITEM_CLASS_作为 TMyThing的替代标记 ,
 //然后用{$Include} 批示符来导入接口模板单元的代码。
 //接下来,你只需将List容器的实际类型声明为模板标记
 // Implementation 部分更加简单,只需要加入{$Include}就能编译你的第一个模板类
Interface Templates
//Interface templates have to be handled slightly differently, but there isn’t that much more to do. Let’s start by declaring an interface template for our List _class:
 //接口模口稍微有一点不同,但不需要再做很多。先让我们为List类声明一个接口模板:
_LIST_INTF_ = interface
[_LIST_INTF_GUID_]
  function GetCount: Integer;
  function GetItem(Idx: Integer): _ITEM_CLASS_;
  function Add: _ITEM_CLASS_;
  procedure Remove(Item: _ITEM_CLASS_);
  procedure Insert(Idx: Integer; Item: _ITEM_CLASS_);
  property Count: Integer
  read GetCount;
  property Item[Idx: Integer]: _ITEM_CLASS_
  read GetItem;
end;

{
You will notice that there is a marker for a GUID enclosed in square brackets; this is because you can only generate the string that represents the GUID outside of this template. Here is the code for a concrete interface based on this template:
你可能注意到,在方括号里有一个包含GUID字母的标记;这是因为你只能生成这种模板(通过GUID来区别)的标识符。以下是一个基于这个模板的具体接口代码
}

const
  _LIST_INTF_GUID_ = '{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}';

type
  _ITEM_CLASS_ = TMyThing;
  {$I ListIntfTemplate}
  IMyThingList = _LIST_INTF_;

{
Of course you could then go on to create a List interface template that manages list of interfaces.
Conclusion
C++ programmers are not as privileged as they thought they were. Next time one of them tries to rub your nose in the inadequacies of Delphi, just show them this article.
当然,你应该接下来创建一个List接口模板来管理接口
结论
不只是C++程序员才享有模板的特权!以后,在他们试图嘲笑Delphi的不充分时,把这篇文章Show给他们看。
 }












转载于:https://www.cnblogs.com/tulater/archive/2008/10/09/1307434.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值