熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Delphi編程 >> 正文

Delphi2009初體驗-語言篇-體驗泛型(二)

2022-06-13   來源: Delphi編程 

  六體驗泛型數組

  七體驗泛型方法

  八體驗自定義泛型類

  九體驗泛型約束條件

  類類型約束條件

  對象類型約束條件

  構造函數約束條件

  值類型約束條件

  多約束條件

  多模板類型分別約束條件

  嵌套約束條件

  十關於特化與偏特化

  十一 總結

  由於正式版還沒有發出官方的幫助文檔也沒有洩露所以我沒有辦法驗證Delphi對泛型的支持到何種程度了大家對泛型都很熟悉具體細節我就不多說了下面將貼出一些代碼用來驗證Delphi對泛型的支持並驗證是否通過

  體驗泛型數組

program TestGenericArray;

{$APPTYPE CONSOLE}

uses
  SysUtils;

type
  TArr<T> = array of T;

var
  arr: TArr<Integer>;
  n: Integer;
begin
  Setlength(arr );

  for n := to do
  begin
    arr[n] := n;
  end;
end


   體驗泛型方法

  Delphi不支持全局泛型方法泛型方法只能置於類內或者嵌套在方法內或者成為類的靜態方法

  以下代碼將打印出傳入泛型變量的地址

program TestGenericArray;

{$APPTYPE CONSOLE}

uses
  SysUtils;

type
  TGeneric = class
    class procedure PrintAddress<T>(aVal: T);
  end;

var
  n: Integer;

{ TGeneric }

class procedure TGenericPrintAddress<T>(aVal: T);
begin
  Writeln(Integer(@aVal));
end;

begin
  n := ;
  TGenericPrintAddress<Integer>(n);
end

  Delphi2009初體驗 - 語言篇 - 體驗泛型(二)

  體驗自定義泛型類

program TestGenericClass;

{$APPTYPE CONSOLE}

uses
 SysUtils;

type
  TGenericsClass<T> = class
  private
    fValue: T;
  public
    constructor Create(aValue: T); virtual;
    property Value: T read fValue write fValue;
  end;

var
  gc: TGenericsClass<Integer>;

{ TGenericsClass<T> }

constructor TGenericsClass<T>Create(aValue: T);
begin
  fValue := aValue;
end;

begin
  gc := TGenericsClass<Integer>Create();
  Writeln(gcValue);
  FreeAndNil(gc);

  Readln;
end

  Delphi2009初體驗 - 語言篇 - 體驗泛型(二)

  體驗泛型約束條件

  以下通過代碼針對泛型類對Delphi所支持的泛型約束條件進行驗證

  類類型約束條件

  約束模板類型T只能為類類型

program TestGenericClass;

{$APPTYPE CONSOLE}

uses
  SysUtils;

type
  TGenericsClass<T: class> = class // 注意在此進行約束
  private
    fValue: T;
  public
    constructor Create(aValue: T); virtual;
    property Value: T read fValue write fValue;
  end;

var
  gc: TGenericsClass<TObject>;

{ TGenericsClass<T> }

constructor TGenericsClass<T>Create(aValue: T);
begin
  fValue := aValue;
end;

begin
  gc := TGenericsClass<TObject>Create(nil);
  Writeln(gcValue = nil);
  FreeAndNil(gc);

  Readln;
end

  對象類型約束條件

  約束T只能為某一個對象類型

program TestGenericArray;

{$APPTYPE CONSOLE}

uses
  SysUtils
  Classes
  Contnrs;

type
  TGenericsClass<T: TList> = class // 注意在此進行約束
  private
    fValue: T;
  public
    constructor Create(aValue: T); virtual;
    property Value: T read fValue write fValue;
  end;

var
  gc: TGenericsClass<TObjectList>;

{ TGenericsClass<T> }

constructor TGenericsClass<T>Create(aValue: T);
begin
  fValue := aValue;
end;

begin
  gc := TGenericsClass<TObjectList>Create(nil);
  Writeln(gcValue = nil);
  FreeAndNil(gc);

  Readln;
end
    構造函數約束條件

  大家都知道在C#中可以使用 T where new() 對泛型模板類型進行構造函數的約束指明 類型T 必須有一個可見的構造函數

  在D我也發現有這樣的特性

TGeneric<T: constructor> = class
public
  constructor Create; virtual;
end;

    約束 constructor表明T必須擁有可見的構造函數

  但是我在使用以下代碼時編譯器總是提示編譯不通過

var
  t: T;
begin
  t := TCreate;
end;

  獲取是另外一種寫法?我沒有嘗試出來需要等官方正式版出來才能確認

  值類型約束條件

  Delphi的泛型約束不提供值類型約束條件TGenericsClass<T Integer> = class這樣的約束編譯器是不支持的所以像c++中template <Tint S> class TBuf這樣的約束在Delphi中行不通

  多約束條件

  與C#類似Delphi的多約束條件用來約束T既滿足一個類型又滿足一個接口

program TestGenericArray;

{$APPTYPE CONSOLE}

uses
  SysUtils
  Classes
  Windows
  Contnrs;

type
  IInt = Interface
    procedure Test;
  End;

  TImp = class(TInterfacedObject IInt)
  public
    procedure Test;
  end;

  TGenericsClass<T: class IInt> = class // 注意在此進行約束
  private
    fValue: T;
  public
    constructor Create(aValue: T); virtual;
    property Value: T read fValue write fValue;
  end;

var
  gc: TGenericsClass<TImp>;

{ TGenericsClass<T> }

constructor TGenericsClass<T>Create(aValue: T);
begin
  fValue := aValue;
end;

{ TImp }

procedure TImpTest;
begin

end;

begin
  gc := TGenericsClass<TImp>Create(nil);
  Writeln(gcValue = nil);
  FreeAndNil(gc);

  Readln;
end

    多模板類型分別約束條件

  有兩個模板類型TT要使用不同的約束分別約束兩個模板類型可以使用以下方法

type
  TGenericsClass<T: class; T: TList> = class // 注意在此進行約束將兩個模板類型分開進行分別約束
  private
  end;
嵌套約束條件

    Delphi的泛型約束條件對嵌套約束條件處理的很好

TFelix<T> = class
  public

  end;

  TGenericsClass<T: class; T: TFelix<T>> = class // 注意在此進行約束將兩個模板類型分開進行分別約束
  private
  end;

    關於特化和偏特化

  謝謝網友裝配腦袋的提醒我試了很多方法都沒有跡象表明D支持C++中模板的特化和偏特化或者D用其他形式的語法表示特化與偏特化導致我沒有試驗出來

  十一總結

  總體上來說D從泛型的角度出發做得已經非常不錯了已經非常接近C#甚至D還提供類似於C#的關鍵字default來獲取泛型類型T的默認值(值類型置引用類型為空指針)

  在接下來的章節裡我會向大家介紹D的其他新體驗匿名函數和反射(比RTTI更強大)的支持


From:http://tw.wingwit.com/Article/program/Delphi/201311/24664.html
    推薦文章
    Copyright © 2005-2022 電腦知識網 Computer Knowledge   All rights reserved.