Delphi泛型应用示例之一:接口化指针

来源:互联网 发布:wifi定位算法研究 编辑:程序博客网 时间:2024/05/17 09:24



接口的引用计数特性可以让我们方便地创建一个接口实例,它可以到处使用而无需手动释放内存。但是假如我们这个接口里面有很多数据项那就麻烦多了,得针对每个数据项分别写出其Get和Set方法,接口要写一遍,类还要写一遍。


举个例子,我们想把这个记录类型用接口的方式实现:
  TRecord_Test = record
    Data1: string;
    Data2: Integer;
    Data3: Double;
  end;

通常的方法是这样的:
type
  TInterface_Test = interface
    function GetData1: string;
    function GetData2: Integer;
    function GetData3: Double;
    procedure SetData1(const Value: string);
    procedure SetData2(const Value: Integer);
    procedure SetData3(const Value: Double);
    property Data1: string read GetData1 write SetData1;
    property Data2: Integer read GetData2 write SetData2;
    property Data3: Double read GetData3 write SetData3;
  end;

  TClass_Test = class(TInterfacedObject, TInterface_Test)
  private
    FData2: Integer;
    FData3: Double;
    FData1: string;
    function GetData1: string;
    function GetData2: Integer;
    function GetData3: Double;
    procedure SetData1(const Value: string);
    procedure SetData2(const Value: Integer);
    procedure SetData3(const Value: Double);
  public
    property Data1: string read GetData1 write SetData1;
    property Data2: Integer read GetData2 write SetData2;
    property Data3: Double read GetData3 write SetData3;
  end;

implementation

{ TClass_Test }
function TClass_Test.GetData1: string;
begin
  Result := FData1;
end;

function TClass_Test.GetData2: Integer;
begin
  Result := FData2;
end;

function TClass_Test.GetData3: Double;
begin
  Result := FData3;
end;

procedure TClass_Test.SetData1(const Value: string);
begin
  FData1 := Value;
end;

procedure TClass_Test.SetData2(const Value: Integer);
begin
  FData2 := Value;
end;

procedure TClass_Test.SetData3(const Value: Double);
begin
  FData3 := Value;
end;




上面的代码是不是看得人吐血?要是有多个类似的记录,恐怕大家宁愿到处维护指针了。
不要紧,我们有万能的泛型。请看下述代码:



unit BambooInterfacedPointer;

interface

type
  TValuePointer<T> = packed record
    PValue: ^T;
  end;

  IBambooInterfacedPointer<T> = interface
    function Instance: TValuePointer<T>;
  end;

  TBambooInterfacedPointer<T> = class(TInterfacedObject, IBambooInterfacedPointer<T>)
  strict private
    FValuePointer: ^T;
  private
    function Instance: TValuePointer<T>; inline;
  public
    constructor Create;
    destructor Destroy; override;
  end;

implementation

{ TBambooInterfacedPointer<T> }

constructor TBambooInterfacedPointer<T>.Create;
begin
  inherited Create;
  New(FValuePointer);
  System.FillChar(FValuePointer^, SizeOf(T), 0);
end;

destructor TBambooInterfacedPointer<T>.Destroy;
begin
  Dispose(FValuePointer);
  inherited Destroy;
end;

function TBambooInterfacedPointer<T>.Instance: TValuePointer<T>;
begin
  Result.PValue := FValuePointer;
end;

end.


说明一下,之所以要定义
type
TValuePointer<T> = packed record
PValue: ^T;
end;

这么一个东西,是因为在泛型接口里面不允许使用如下写法
IBambooInterfacedPointer<T> = interface
function Instance: ^T;
end;
所以定义了一个记录类型来作为过渡。



最后,则是我写的这个接口化指针的应用实例:

type
  TRecord_Test = record
    Data1: string;
    Data2: Integer;
    Data3: Double;
  end;

var
  aInterfacedPointer: IBambooInterfacedPointer<TRecord_Test>;

begin
  aInterfacedPointer := TBambooInterfacedPointer<TRecord_Test>.Create;
  with aInterfacedPointer.Instance.PValue^ do
  begin
    Data1 := '123';
    Data2 := 456;
    Data3 := 7.89;
  end;
end;

是不是很方便啊 ? 重要的是 , 所有的数据类型都可以这么干 !



0 0
原创粉丝点击