程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> Delphi >> Delphi2009初體驗 - 語言篇 - 體驗泛型(二)

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

編輯:Delphi

六、體驗泛型數組

七、體驗泛型方法

八、體驗自定義泛型類

九、體驗泛型約束條件

1、類類型約束條件

2、對象類型約束條件

3、構造函數約束條件

4、值類型約束條件

5、多約束條件

6、多模板類型分別約束條件

7、嵌套約束條件

十、關於特化與偏特化

十一、總結

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

六、體驗泛型數組

1program TestGenericArray;
2
3{$APPTYPE CONSOLE}
4
5uses
6  SysUtils;
7
8type
9  TArr<T> = array of T;
10
11var
12  arr: TArr<Integer>;
13  n: Integer;
14begin
15  Setlength(arr, 10);
16
17  for n := 0 to 9 do
18  begin
19    arr[n] := n;
20  end;
21end.
22

七、體驗泛型方法

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

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

1program TestGenericArray;
2
3{$APPTYPE CONSOLE}
4
5uses
6  SysUtils;
7
8type
9  TGeneric = class
10    class procedure PrintAddress<T>(aVal: T);
11  end;
12
13var
14  n: Integer;
15
16{ TGeneric }
17
18class procedure TGeneric.PrintAddress<T>(aVal: T);
19begin
20  Writeln(Integer(@aVal));
21end;
22
23begin
24  n := 10;
25  TGeneric.PrintAddress<Integer>(n);
26end.

八、體驗自定義泛型類1program TestGenericClass;
2
3{$APPTYPE CONSOLE}
4
5uses
6 SysUtils;
7
8type
9  TGenericsClass1<T> = class
10  private
11    fValue: T;
12  public
13    constructor Create(aValue: T); virtual;
14    property Value: T read fValue write fValue;
15  end;
16
17var
18  gc1: TGenericsClass1<Integer>;
19
20{ TGenericsClass1<T> }
21
22constructor TGenericsClass1<T>.Create(aValue: T);
23begin
24  fValue := aValue;
25end;
26
27begin
28  gc1 := TGenericsClass1<Integer>.Create(10);
29  Writeln(gc1.Value);
30  FreeAndNil(gc1);
31
32  Readln;
33end.

九、體驗泛型約束條件

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

1、類類型約束條件

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

1program TestGenericClass;
2
3{$APPTYPE CONSOLE}
4
5uses
6  SysUtils;
7
8type
9  TGenericsClass1<T: class> = class // 注意在此進行約束
10  private
11    fValue: T;
12  public
13    constructor Create(aValue: T); virtual;
14    property Value: T read fValue write fValue;
15  end;
16
17var
18  gc1: TGenericsClass1<TObject>;
19
20{ TGenericsClass1<T> }
21
22constructor TGenericsClass1<T>.Create(aValue: T);
23begin
24  fValue := aValue;
25end;
26
27begin
28  gc1 := TGenericsClass1<TObject>.Create(nil);
29  Writeln(gc1.Value = nil);
30  FreeAndNil(gc1);
31
32  Readln;
33end.

2、對象類型約束條件

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

1program TestGenericArray;
2
3{$APPTYPE CONSOLE}
4
5uses
6  SysUtils,
7  Classes,
8  Contnrs;
9
10type
11  TGenericsClass1<T: TList> = class // 注意在此進行約束
12  private
13    fValue: T;
14  public
15    constructor Create(aValue: T); virtual;
16    property Value: T read fValue write fValue;
17  end;
18
19var
20  gc1: TGenericsClass1<TObjectList>;
21
22{ TGenericsClass1<T> }
23
24constructor TGenericsClass1<T>.Create(aValue: T);
25begin
26  fValue := aValue;
27end;
28
29begin
30  gc1 := TGenericsClass1<TObjectList>.Create(nil);
31  Writeln(gc1.Value = nil);
32  FreeAndNil(gc1);
33
34  Readln;
35end.

3、構造函數約束條件

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

在D2009中,我也發現有這樣的特性:

1TGeneric<T: constructor> = class
2public
3  constructor Create; virtual;
4end;

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

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

1var
2  t: T;
3begin
4  t := T.Create;
5end;

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

4、值類型約束條件

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

5、多約束條件

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

1program TestGenericArray;
2
3{$APPTYPE CONSOLE}
4
5uses
6  SysUtils,
7  Classes,
8  Windows,
9  Contnrs;
10
11type
12  IInt = Interface
13    procedure Test;
14  End;
15
16  TImp = class(TInterfacedObject, IInt)
17  public
18    procedure Test;
19  end;
20
21  TGenericsClass<T: class, IInt> = class // 注意在此進行約束
22  private
23    fValue: T;
24  public
25    constructor Create(aValue: T); virtual;
26    property Value: T read fValue write fValue;
27  end;
28
29var
30  gc1: TGenericsClass<TImp>;
31
32{ TGenericsClass<T> }
33
34constructor TGenericsClass<T>.Create(aValue: T);
35begin
36  fValue := aValue;
37end;
38
39{ TImp }
40
41procedure TImp.Test;
42begin
43
44end;
45
46begin
47  gc1 := TGenericsClass<TImp>.Create(nil);
48  Writeln(gc1.Value = nil);
49  FreeAndNil(gc1);
50
51  Readln;
52end.

6、多模板類型分別約束條件

有兩個模板類型T1、T2,要使用不同的約束分別約束兩個模板類型,可以使用以下方法:

1type
2  TGenericsClass<T: class; T1: TList> = class // 注意在此進行約束,用“;”將兩個模板類型分開進行分別約束
3  private
4  end;
7、嵌套約束條件

Delphi2009的泛型約束條件對嵌套約束條件處理的很好,如:

1TFelix<T> = class
2  public
3
4  end;
5
6  TGenericsClass<T: class; T1: TFelix<T>> = class // 注意在此進行約束,用“;”將兩個模板類型分開進行分別約束
7  private
8  end;

十、關於特化和偏特化

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

十一、總結

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

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

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved