Delphi.NET 內(nèi)部實現(xiàn)分析(3.4)
由此我們可以看出,Delphi.NET中使用了從內(nèi)嵌子類到class helper種種方法,
才總算解決了從傳統(tǒng)繼承模型和內(nèi)存模型遷移到CLR以及FCL類樹的過程,遷移過程不可謂不艱辛。
雖然這種解決方法不能算是完美,但相信Borland也是在綜合評估了諸多其它手段之后,
才做出這樣的選擇,付出了一些代價、如class helper,也取得了不少的成果、源代碼級兼容較強。
這種映射模型到底行不行,我想只能有待時間來做評論。
最后我們來看看Delphi的is和as關(guān)鍵字是如何在Delphi.NET中實現(xiàn)的
//-----------------------------------------Borland.Delphi.System.pas--
function _IsClass(Obj:TObject; Cls:TClass): Boolean;
var
t1, t2: System.Type;
begin
if not Assigned(Obj) then
Result := false
else
begin
t1 := Obj.GetType;
t2 := System.Type.GetTypeFromHandle(_TClass(Cls).FInstanceType);
if t1 = t2 then
Result := true
else
Result := t1.IsSubclassOf(t2);
end;
end;
//-----------------------------------------Borland.Delphi.System.pas--
_IsClass函數(shù)實現(xiàn)很簡單,檢測對象有效性后直接通過判斷兩個類型的繼承關(guān)系檢測。
//-----------------------------------------System.pas--
function _IsClass(Child: TObject; Parent: TClass): Boolean;
begin
Result := (Child <> nil) and Child.InheritsFrom(Parent);
end;
//-----------------------------------------System.pas--
相比之下Delphi的is實現(xiàn)更簡單,直接用TObject.InheritsFrom實現(xiàn)。
Delphi.NET之所以不象Delphi那樣直接使用TObject.InheritsFrom實現(xiàn)is關(guān)鍵字,
是因為相對于Type.IsSubclassOf方法來說,TObjectHelper.InheritsFrom方法
使用的Type.IsInstanceOfType方法代價較大。
Type.IsSubclassOf方法只是從傳入類型開始,一級一級查看其父類是否自己。
//-----------------------------------------Type.cs--
public abstract class Type : MemberInfo, IReflect
{
public virtual bool IsSubclassOf(Type c)
{
Type p = this;
if (p == c)
return false;
while (p != null) {
if (p == c)
return true;
p = p.BaseType;
}
return false;
}
}
//-----------------------------------------Type.cs--
而Type.IsInstanceOfType則要考慮Remoting、COM、接口以及運行時類型等等
諸多復(fù)雜因素,因而不適合用在is/as這樣頻繁使用的關(guān)鍵字實現(xiàn)上。
//-----------------------------------------Borland.Delphi.System.pas--
function _AsClass(Obj:TObject; Cls:TClass): TObject;
begin
Result := Obj;
if not _IsClass(Obj, Cls) then
raise System.FormatException.Create(‘Invalid Cast‘);
end;
//-----------------------------------------Borland.Delphi.System.pas--
as操作符的實現(xiàn),只是簡單的賦值加檢測而已,因為CLR是單根結(jié)構(gòu),所以轉(zhuǎn)換總是成功的,
只需在轉(zhuǎn)換后用is操作符檢測,拋出異常情況就行。
//-----------------------------------------System.pas--
function _AsClass(Child: TObject; Parent: TClass): TObject;
{$IFDEF PUREPASCAL}
begin
Result := Child;
if not (Child is Parent) then
Error(reInvalidCast); // loses return address
end;
//-----------------------------------------System.pas--
可以看到Delphi中的實現(xiàn)也是非常類似的。
最后一個相關(guān)函數(shù)是_ClassCreate,用于實現(xiàn)類型的創(chuàng)建與構(gòu)造。
//-----------------------------------------Borland.Delphi.System.pas--
function _ClassCreate(Cls: TClass; Params: Array of TObject): TObject;
begin
Result := System.Activator.CreateInstance(Cls.SystemType, Params);
end;
//-----------------------------------------Borland.Delphi.System.pas--
與Delphi的System.pas中冗長的_ClassCreate函數(shù)實現(xiàn)相比,Delphi.NET無需關(guān)心
類的內(nèi)存獲取、構(gòu)造異常的截獲以及Self指針的修正等等,只是簡潔的通過System.Activator類
完成所需功能,這就是底層有一個強大完善類庫支持的優(yōu)勢所在。
至此,Borland.Delphi.System單元中關(guān)于元類、類與對象的相關(guān)定義及實現(xiàn)就基本上分析完了,
雖然只有寥寥百來行代碼,但它為Delphi在CLR上的映射打下了堅實的基礎(chǔ)。
下一節(jié)我們將進一步看看Delphi中消息與方法的映射關(guān)系是如何在Delphi.NET中模擬的。