Delphi.NET 內部實(shí)現分析(3.4)
由此我們可以看出,Delphi.NET中使用了從內嵌子類(lèi)到class helper種種方法,
才總算解決了從傳統繼承模型和內存模型遷移到CLR以及FCL類(lèi)樹(shù)的過(guò)程,遷移過(guò)程不可謂不艱辛。
雖然這種解決方法不能算是完美,但相信Borland也是在綜合評估了諸多其它手段之后,
才做出這樣的選擇,付出了一些代價(jià)、如class helper,也取得了不少的成果、源代碼級兼容較強。
這種映射模型到底行不行,我想只能有待時(shí)間來(lái)做評論。
最后我們來(lái)看看Delphi的is和as關(guān)鍵字是如何在Delphi.NET中實(shí)現的
//-----------------------------------------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í)現很簡(jiǎn)單,檢測對象有效性后直接通過(guò)判斷兩個(gè)類(lèi)型的繼承關(guān)系檢測。
//-----------------------------------------System.pas--
function _IsClass(Child: TObject; Parent: TClass): Boolean;
begin
Result := (Child <> nil) and Child.InheritsFrom(Parent);
end;
//-----------------------------------------System.pas--
相比之下Delphi的is實(shí)現更簡(jiǎn)單,直接用TObject.InheritsFrom實(shí)現。
Delphi.NET之所以不象Delphi那樣直接使用TObject.InheritsFrom實(shí)現is關(guān)鍵字,
是因為相對于Type.IsSubclassOf方法來(lái)說(shuō),TObjectHelper.InheritsFrom方法
使用的Type.IsInstanceOfType方法代價(jià)較大。
Type.IsSubclassOf方法只是從傳入類(lèi)型開(kāi)始,一級一級查看其父類(lèi)是否自己。
//-----------------------------------------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、接口以及運行時(shí)類(lèi)型等等
諸多復雜因素,因而不適合用在is/as這樣頻繁使用的關(guān)鍵字實(shí)現上。
//-----------------------------------------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操作符的實(shí)現,只是簡(jiǎn)單的賦值加檢測而已,因為CLR是單根結構,所以轉換總是成功的,
只需在轉換后用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中的實(shí)現也是非常類(lèi)似的。
最后一個(gè)相關(guān)函數是_ClassCreate,用于實(shí)現類(lèi)型的創(chuàng )建與構造。
//-----------------------------------------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中冗長(cháng)的_ClassCreate函數實(shí)現相比,Delphi.NET無(wú)需關(guān)心
類(lèi)的內存獲取、構造異常的截獲以及Self指針的修正等等,只是簡(jiǎn)潔的通過(guò)System.Activator類(lèi)
完成所需功能,這就是底層有一個(gè)強大完善類(lèi)庫支持的優(yōu)勢所在。
至此,Borland.Delphi.System單元中關(guān)于元類(lèi)、類(lèi)與對象的相關(guān)定義及實(shí)現就基本上分析完了,
雖然只有寥寥百來(lái)行代碼,但它為Delphi在CLR上的映射打下了堅實(shí)的基礎。
下一節我們將進(jìn)一步看看Delphi中消息與方法的映射關(guān)系是如何在Delphi.NET中模擬的。
聯(lián)系客服