您的位置:首页 > 编程语言 > Delphi

Delphi泛型结合接口的应用 (译自Delphi2009 Handbook)

2010-08-28 11:17 323 查看
            通过接受一个限定的参数,这个参数是实现某个接口的类,比较起直接接受泛型,而限制这个泛型的类要更加灵活。也就是通常所说的面向接口式的编程。这样可以达到调用实现了这个接口的各种泛型的实例。这种对泛型使用接口约束的应用,在.net框架中有很广泛的应用。下面是一个实例(命名为IntfConstraint)。

 

            首先,需要声明一个接口:

type
IGetValue = interface
['{60700EC4-2CDA-4CD1-A1A2-07973D9D2444}']
function GetValue: Integer;
procedure SetValue (Value: Integer);
property Value: Integer
read GetValue write SetValue;
end;


 

         接下来我们定义一个类实现这个接口:

TGetValue = class (TSingletonImplementation, IGetValue)
private
fValue: Integer;
public
constructor Create (Value: Integer); // = 0);
function GetValue: Integer;
procedure SetValue (Value: Integer);
end;


 

        精彩内容从下面开始,接着我们定义一个泛型类,这泛型类被限定了是实现了(我们上面定义的)指定的接口:

TInftClass <T: IGetValue> = class
private
val1, val2: T; // or IGetValue
public
procedure Set1 (val: T);
procedure Set2 (val: T);
function GetMin: Integer;
function GetAverage: Integer;
procedure IncreaseByTen;
end;


 

          这个类的泛型方法如下:

function TInftClass<T>.GetMin: Integer;
begin
if Assigned (val1) and Assigned (val2) then
Result := min (val1.GetValue, val2.GetValue)
else
Result := 0;
end;

procedure TInftClass<T>.IncreaseByTen;
begin
if Assigned (val1) and Assigned (val2) then
begin
val1.SetValue (val1.GetValue + 10);
val2.SetValue (val2.GetValue + 10);
end;
end;


 

 

        有了如上的定义,我们可以这样使用这个泛型类(数值型参数,接着还有其他类型参数的):

procedure TFormIntfConstraint.btnValueClick(Sender: TObject);
var
iClass: TInftClass<TGetValue>;
begin
iClass := TInftClass<TGetValue>.Create;
try
iClass.Set1 (TGetValue.Create (5));
iClass.Set2 (TGetValue.Create (25));
Log ('Average: ' + IntToStr (iClass.GetAverage));
iClass.IncreaseByTen;
Log ('Min: ' + IntToStr (iClass.GetMin));
finally
iClass.val1.Free;
iClass.val2.Free;
iCLass.Free;
end;
end;


 

 

 

         为了展现这个泛型类的灵活性,我又建立了一个完全不同的(对GetValue接口)的实现:

// IGetValue 的第二种实现 , 对TButton对象
TButtonValue = class (TButton, IGetValue)
public
function GetValue: Integer;
procedure SetValue (Value: Integer);
class function MakeTButtonValue (
Owner: TComponent; Parent: TWinControl): TButtonValue;
end;


 

       

     ButtonValue中,生成按钮坐标位置(随机位置,在父对象中)的成员函数,这个和主题关系不大,所以收缩

// ButtonValue 成员函数,用来生成按钮的坐标位置
class function TButtonValue.MakeTButtonValue(Owner: TComponent;
Parent: TWinControl): TButtonValue;
begin
Result := TButtonValue.Create(Owner);
Result.Parent := Parent;
Result.SetBounds(
Random (Parent.Width), Random (Parent.Height),
Result.Width, Result.Height);
Result.Caption := 'btnv';
end;


 

        ButtonVaule中GetVaule和SetValue实现:

// ButtonValue 中实现GetValue 和SetValue
function TButtonValue.GetValue: Integer;
begin
Result := Left;
end;

procedure TButtonValue.SetValue(Value: Integer);
begin
Left := Value;
end;


 

 

       下面是第二种(按钮坐标)泛型类的使用:

// 主窗体中测试第二种(按钮的位置)泛型调用
procedure TFormIntfConstraint.btnValueButtonClick(Sender: TObject);
var
iClass: TInftClass<TButtonValue>;
begin
iClass := TInftClass<TButtonValue>.Create;
try
iClass.Set1 (TButtonValue.MakeTButtonValue (self, ScrollBox1));
iClass.Set2 (TButtonValue.MakeTButtonValue (self, ScrollBox1));
Log ('Average: ' + IntToStr (iClass.GetAverage));
Log ('Min: ' + IntToStr (iClass.GetMin));
iClass.IncreaseByTen;
Log ('New Average: ' + IntToStr (iClass.GetAverage));
finally
iClass.Free;
end;
end;


 

 

 

 源代码下载  (已添加了中文注释)

 

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息