新時代的開端:DELPHI.NET- 語言篇

新時代的開端:DELPHI.NET- 語言篇
文/黃忠成(2004/1/1,原文刊登於PC 電腦傳真月刊)
DELPHI.NET
在經過近兩年的漫長等待後,Borland 終於在2003 年的耶誕前夕釋出了DELPHI 8
for .NET Framework 的正式版本,此舉不但粉碎了DELPHI 已死的揣測,也正式將DELPHI
使用者帶入了.NET 的世界。藉由VCL.NET,原DELPHI 使用者可以延用以往所開發的
元件或是程式,用幾乎相同的方式撰寫.NET Windows Application。除此之外,
DELPHI.NET 也支援.NET WinForm 及ASP.NET 的應用程式開發,這就像是DELPHI 一
貫的傳統:支援最多的環境,提供多樣化的開發技術,讓使用者得到最大的應用空間。
當然,不可否認,DELPHI.NET 畢竟是一個新的開發環境及一個加強後的DELPHI 語言,
要說完全無痛升級是不可能的,程式設計師應該要有一個認知,在Windows 時代,API
是不可缺的知識,在今日的.NET 時代也不例外,了解.NET Framework 是基本的要求。
針對DELPHI.NET 所提供的各種新功能及新語言特色,筆者規畫了一系列文章,希望
能幫助原DELPHI 的使用者快速的進入DELPHI.NET 的世界,現在就讓我們開始這一趟
旅程吧。
Imporved! Namespace(命名空間)
事實上,Namespace 並非是在DELPHI.NET 中第一次出現,早在DELPHI 時代就已具
備基本的Namespace 概念,只是當時此技術尚未成熟,大多數時候只是用來解決模糊呼
叫或是定義等問題,下面的程式碼片段是在DELPHI 時代使用該技術的範例。
Dialogs.ShowMessage(AMsg);
當時,這種技術頂多只能稱之為Unit 的分割,離真正的Namespace 尚有段距離。為了
符合CLS 規格,DELPHI.NET 加入了真正的Namespace 機制,使編譯後的Assembly 能
為其它CLS 相容語言所用,其基本用法與以往大致相同。
unit MyCompany.MyProduct.Unit2;
interface
uses Borland.Vcl.Classes,Borland.Vcl.SysUtils;
與DELPHI 相同,DELPHI.NET 的Unit 檔名需與unit ...部份同名,另外原先的Classes、
SysUtils 等Unit 也都納入了Borland.Vcl 這個Namespace 之中,不過使用者並不需特別
修改以往的程式來符合這個改變,藉由編譯器預設Namespace 搜尋功能,使用者仍可使
用uses Classes,SysUtils 方式來處理,編譯器自會代為轉換。提醒讀者,目前DELPHI.NET
仍只支援在一個Unit 中定義單一Namespace,並不允許同一Unit 擁有多個Namespace。
另外DELPHI.NET Unit 也不支援類似C#等語言中以明確定義代替uses 的方式,簡單的
說就是要引用Unit2 才能使用其中的定義,不能省略掉引用Unit2 部份,直接使用
Unit2.xxx 方式宣告。
New! 成員視界
在DELPHI.NET 中,除了原有的private、protected、public、published 四個視界外,還
加入了strict private、strict protected 兩個新的成員視界,此舉是為了符合CLS 規格。原先
的DELPHI 中,private、protected 在同一Unit 中是被視同為public 視界的,下面的程式碼
說明了此點。
type
TMyClass = class
private
FData:Integer;
end;
...............
vObj := TMyClass.Create;
vObj.FData := 100; //OK!
這個特性仍被延用至DELPHI.NET,事實上它們被對應至Assembly or Family、Assembly
and Family 兩個CLS 所規範的視界,而strict private 及strict protected 則對應到真實的
private、protected 兩個視界,表一列出目前DELPHI.NET 的視界對應及存取限制。
TMyClass = class
strict private
FPrivateData:Integer;
private
FData:Integer;
end;
.............
vObj := TMyClass.Create;
vObj.FData := 100; //OK
vObj.FPrivateData := 100; //Error
DELPHI.NET C# CLS 說明
private internal Assembly 該類別或同一Assembly 才可存取。
protected internal protected Assembly or Family 同一Assembly 或子類別才可存取。
public public Public 不限。
strict private private Private 該類別中才可存取。
strict protected protected Family 該類別及其子類別才可存取。
New! class var(靜態成員變數)
對DELPHI 使用者來說,靜態成員變數是個新功能,以往多是以全域變數來達到相同
效果,使用靜態成員可以有效的將設計師由全域變數的窠臼中解放。
TMyClass = class(TObject)
class var
InstanceCount:Integer;
..................
constructor TMyClass.Create;
begin
TMyClass.InstanceCount := TMyClass.InstanceCount+1;
inherited Create;
end;
destructor TMyClass.Destroy;
begin
TMyClass.InstanceCount := TMyClass.InstanceCount-1;
inherited Destroy;
end;
..................
TMyClass.Create;
TMyClass.Create;
TMyClass.Create;
ShowMessage(IntToStr(TMyClass.InstanceCount)); // 3.
class var 與一般成員相同,也具備了視界的觀念。
New! static member function(靜態成員函式)
事實上,DELPHI 中早就具備了靜態成員函式的功能,當時稱為class method,
DELPHI.NET 除了繼續延用此概念外,還加入了static method 的支援,這點主要是針對
CLS 的規格而定。但是目前On-Line Help 在描述語法時似乎有誤,其內的範例是在一般
的method 後加上static 即可成為靜態成員函式,但實際上編譯器並不接受此語法,在筆
者觀察VCL 的原始碼後,正確的用法應該如下所示。
TMyClass = class(TObject)
class var
InstanceCount:Integer;
public
...............
class procedure ShowInstanceCount; static;
end;
class procedure 是否加上static 的關鍵字,會影響編譯器所產生的IL 程式碼,假如設計
者希望該函式能為其它CLS 相容語言所用,就必須加上static 關鍵字。
New! static properties(靜態成員屬性)
這也是一個全新的功能,DELPHI.NET 允許設計師定義靜態的成員屬性,其唯一限制
是在屬性的存取函式或是變數都必須是靜態成員。
TMyClass = class(TObject)
strict private
class procedure SetData(AData:Integer);static;
class function GetData:Integer;static;
class var
FData : Integer;
public
class property Data:Integer read GetData write SetData;
end;
.........
TMyClass.Data := 100;
ShowMessage(IntToStr(TMyClass.Data)); //100
New! static construtcor(靜態建構子)
在DELLPHI.NET 中,靜態建構子(class constructor)可用來初使化靜態成員。
TMyClass = class(TObject)
class var
FDataVar : Integer;
public
class constructor Create;
end;
..............
class constructor TMyClass.Create;
begin
FDataVar := 1000;
end;
......
ShowMessage(IntToStr(TMyClass.FDataVar)); // 1000
基本上,DELPHI.NET 提供了完整的靜態成員支援,而其是由原本的class member 所延
伸而來。
New! Nested Type(巢狀型別)
這也是為了符合CLS 所添加的新功能,DELPHI.NET 允許設計師在某個類別中定義
一個子類別,需注意的一點是DELPHI.NET 的Nested Type 並不受視界影響,即使將子
類別宣告於strict private 之中,實際上所編譯出來的仍然是public。不過設計師仍可延用
以往將類別宣告於implementation 區段後的方式來達到與private 相同效果。
TMyClass = class(TObject)
public
type
TMyClassInner = class(TObject)
public
FData:Integer;
end;
strict private
FInner : TMyClassInner;
.....................
var
vObj2 : TMyClass.TMyClassInner;
begin
vObj2 := TMyClass.TMyClassInner.Create;
..................
New! Sealed Classes(末代類別)
在CLS 規格中允許設計者定義一個seled class,此種類別將不支援繼承,DELPHI.NET
同時也支援了此功能。不過,DELPHI.NET 的on-line help 對此語法的描述是錯誤的,
下面是正確的語法。
TMyClass = class sealed
public
procedure HelloMyClass;
end;
TMyClass2 = class(TMyClass) //Error!
New! Operator Overload(運算子覆載)
運算子覆載對於DELPHI 設計師來說是一個完全嶄新的概念,藉由此功能的幫助,設
計師可以自定類別的運算子行為,提供使用者一個較直覺的應用模式,例如用”+”符號
直接加總兩個物件實體,或是改變物件的型別轉換行為,下面的程式展現了此類運用。
TMyClass = class
strict private
FData:Integer;
public
class operator Add(A,B:TMyClass):TMyClass;
class operator Implicit(A:Integer):TMyClass;
class operator Implicit(A:TMyClass):Integer;
property Data:Integer read FData write FData;
end;
...................
class operator TMyClass.Add(A,B:TMyClass):TMyClass;
begin
Result := TMyClass.Create;
Result.Data := A.Data + B.Data;
end;
class operator TMyClass.Implicit(A:Integer):TMyClass;
begin
Result := TMyClass.Create;
Result.Data := A;
end;
class operator TMyClass.Implicit(A:TMyClass):Integer;
begin
Result := A.Data;
end;
procedure TForm1.FormCreate(Sender: TObject);
var
vObj1,vObj2,vResult,vResult2:TMyClass;
vInt:Integer;
begin
vObj1 := TMyClass.Create;
vObj2 := TMyClass.Create;
vObj1.Data := 100;
vObj2.Data := 100;
vResult := vObj1 + vObj2;
ShowMessage(IntToStr(vResult.Data));
vInt := vResult;
ShowMessage(IntToStr(vInt));
vResult2 := vInt;
ShowMessage(IntToStr(vResult2.Data));
end;
程式中只展示了隱含轉型的覆載,DELPHI.NET 也支援明確轉型的覆載,只要將Implicit
改為Explicit 即可。DELPHI.NET 的運算子覆載技術完全相容於CLS 規格,其它支援運
算子覆載的CLS 語言,如C# 皆可直接引用。不過設計師為此特色興奮之餘,也不能忘
記一點,運算子覆載是個相當嚴肅的課題,當覆載了”+”符號之後,若不覆載其它運算
符號,將令使用者感到困惑,這也是運算子覆載容易造成錯誤的原因。
New! class helper
這不僅是一個全新的功能,同時也是一個嶄新的概念,DELPHI.NET 為了達到整合
VCL.NET 與.NET Framework 的目的,加入了class helper 功能,運用此功能,設計者可
以在不改變既存類別原始設計的方式,延伸該類別,即使該類別是末代類別也不例外,
下面是一個簡單的範例。
TMyClass = class sealed
public
procedure HelloMyClass;
end;
TMyClassHelper = class helper for TMyClass
public
procedure HelloMyClassHelper;
end;
..........
procedure TMyClass.HelloMyClass;
begin
ShowMessage('Hello My Class!');
end;
procedure TMyClassHelper.HelloMyClassHelper;
begin
ShowMessage('Hello My Class Helper!');
end;
...............
var
vObj : TMyClass;
begin
vObj := TMyClass.Create;
vObj.HelloMyClass;
vObj.HelloMyClassHelper;
end;
熟悉Design Patterns 的讀者應該已發現,class helper 有點類似Adapter 及Helper 這兩個
Pattern,是的!基本上class helper 就是這兩個Pattern 的演化,只是DELPHI.NET 採取編
譯器角度來實作,並將細節隱藏。class helper 也支援繼承與虛擬函式的操作,這代表著
class helper 開啟了除繼承外的另一扇延伸之窗,下面的範例展示了此種用法。
TMyClassHelper = class helper for TMyClass
public
procedure HelloMyClassHelper;virtual;
end;
TMyClassHelper2 = class helper(TMyClassHelper) for TMyClass
public
procedure HelloMyClassHelper;override;
end;
需特別注意的一點,因為class helper 的實作方式較一般class 不同,因此不支援strict
private、strict protected 這兩個視界,同時也不能擁有成員變數,只允許靜態成員變數。
class helper 底層運作
相信有些讀者一定對於class helper 內部的實作方式很好奇,筆者也是,所以利用了
ILDASM 及DeCompiler 工具來觀察使用class helper 類別的實作,事實上,class helper
最終的實作碼大致與下面的DELPHI 程式碼相同。
TMyClass = class
public
FData:Integer;
end;
TMyClassHelper = class
public
class procedure ShowData(ASelf:TMyClass);
end;
class procedure TMyClassHelper.ShowData(ASelf:TMyClass);
begin
ShowMessage(IntToStr(ASelf.FData));
end;
procedure TForm1.Button1Click(Sender: TObject);
var
vObj : TMyClass;
begin
vObj := TMyClass.Create;
vObj.FData := 100;
TMyClassHelper.ShowData(vObj);
end;
其技術重點在於將class helper 中的函式編譯為靜態函式,並添加了一個參數,用來傳入
helped object。在呼叫端部份的程式碼則會被展開為呼叫該靜態函式,這些行為都是由
編譯器代勞,下面的程式可以證明這個論點。
procedure TForm1.Button1Click(Sender: TObject);
var
vObj : TMyClass;
vType : System.Type;
Methods : array of MemberInfo;
begin
vObj := TMyClass.Create;
vObj.HelloMyClass;
vObj.HelloMyClassHelper;
{ invoke static function of TMyClassHelper }
vType := TypeOf(TMyClassHelper);
vType.InvokeMember('HelloMyClassHelper',BindingFlags.InvokeMethod,Nil,Nil,[vObj]);
end;
當class helper 含有繼承時,其行為會稍微改變,改採Interface 來處理,由於這個課題還
牽扯到了RTL 部份,礙於篇幅,筆者就不再深入討論了。
PS:InvokeMember 是.NET Reflection 功能的一部份,其功能是由某個型別取出其方法並
呼叫,筆者將其放在下一篇:.NET Framework 中一併討論。
Next,.NET Framework 篇
本篇文章中,筆者以快速的方式引領讀者瀏覽DELPHI.NET 所新增的語言特色,不過
由於篇幅有限,實難詳述每個特色,例如record 中能定義成員函式等較少用到的功能就
被省略了,讀者們可以參考on-line help 來得到筆者所省略掉的其它細節,下次再見了!

转载于:https://www.cnblogs.com/fuyingke/archive/2005/08/06/209110.html

新時代的開端:DELPHI.NET- 語言篇相关推荐

  1. 骑上犀牛 迎向建筑设计的新時代!!!

    学犀牛中文网,王伯年度巨献之作! 外行人说外行话      骑上犀牛  迎向建筑设计的新時代         我是一个建筑和工业设计外行人,没有从事过上述专业也沒有学習过相关专业,只不过出于对犀牛这个 ...

  2. python之父面试谷歌_Python之父Guido Rossum:打造Google第三大開發語言-经管之家官网!...

    Python之父Guido Rossum:打造Google第三大開發語言 酷勤網 23-Jan-10 IT人物 2009年4月1日凌晨,Guido van Rossum(吉多•範羅蘇姆)在Python ...

  3. 潭州python学院12306案例_人工智慧時代來臨,潭州教育開設Python課程帶學員入門機器學習...

    當今時代,隨著人工智慧科技的飛速發展,人工智慧逐漸深入社會生活生産的方方面面.根據<2019中國人工智慧發展報告>相關數據顯示,人工智慧行業的融資規模呈上升趨勢.在當紅的人工智慧領域,機器 ...

  4. 今日芯声 | 台积电或投资3000亿新台币建新工厂,进军高端封测服务

    "今日芯声"是读芯术推出的一档简读栏目,汇聚每日国内外最新最热的AI应用资讯,敬请关注. 1.台积电或投资3000亿新台币建新工厂,进军高端封测服务 据台北时报报道,台积电计划在台 ...

  5. 自贸新机遇 服贸新“石”代 石家庄市成功举办2019石家庄服务贸易发展论坛

    12月19日至20日,"2019石家庄服务贸易发展论坛"在以岭健康城举办,石家庄市商务局常志卷局长代表市政府致欢迎辞. 服务贸易作为服务业对外开放的阵地,是对外贸易转型升级的重要支 ...

  6. 0G(無線技術最早的拓荒時代)

    0G 0G,是指無線技術最早的拓荒時代,即是前蜂巢式技術(Pre-cellular)時代,或稱前行動通訊時代.Push-to-talk,行動電話系統,改進型行動電話系統,AMTS,OLT,MTD,Au ...

  7. 网站运营手册_新媒体代运营模式价格

    新媒体代运营模式价格 公司也更加重视与其他营销网站的合作,大力寻找专业推广工具,尽可能去采取主动的营销方式.通过比较主动地利用资源的优势,去成为主流媒体的工作者.根据这个调查,我们做了三次专题研究.内 ...

  8. Cover Protocol更新赔偿计划 新增三个新COVER代币获赔方

    12月30日,DeFi保险协议Cover Protocol更新其赔偿计划称,已将在Balancer上为COVER-ETH池提供流动性的用户.以及所有持有YETI和YPIE代币(依据快照结果)的用户添加 ...

  9. 13代酷睿移动端处理器:HX、H、P和U系列区别是什么?

    13代酷睿处理器出来了,特别是移动端的处理器已经出现在新款笔记本上了.而新款处理器里面,相对于AMD的奇特命名方式外,英特尔酷睿移动端稍微简单一些.不过看起来还是挺复杂的,感觉比上一代复杂很多. 当然 ...

最新文章

  1. java接收xml数据_关于java后台如何接收xml格式的数据
  2. linux yum 本地源配置
  3. 一元夺宝类项目的被拒
  4. 聊聊 Redis 使用场景
  5. ts 函数声明及泛型函数
  6. 计算机组成与结构实验箱,HQFC-B1计算机组成和数字电路实验箱
  7. 关于静态局部全局变量
  8. CodeForces - 1285D Dr. Evil Underscores(记忆化搜索+字典树)
  9. Java中获取系统日期时间/系统时间
  10. Python接口自动化之Token详解及应用
  11. Linux下多进程服务端客户端模型二(粘包问题与一种解决方法)
  12. Oracle弱智100问
  13. Spring教程– Spring Core Framework教程
  14. 员工效率低下,责任在管理层的数学解释和分析
  15. 系统找不到指定的文件
  16. DIY自己的ubuntu镜像
  17. 拉卡拉做社区电商,有这些优劣势
  18. 论文阅读_Spatial Temporal Graph Convolutional Networks for Skeleton-Based Action Recognition
  19. 宝山区助行业强主体稳增长若干政策措施的实施细则(20条)(征求意见稿)
  20. 0成本无VPS搭建私人导航、图床、音乐服务器 | vercel freewha

热门文章

  1. Win8Metro(C#)数字图像处理--2.12Sobel边缘检测
  2. CCNP路由实验---12、配置分发列表和被动接口
  3. Task三个列子的分享
  4. linux mount命令参数及用法详解
  5. Java 异常基础 Exception
  6. 【基础算法-模拟-例题-*校长的问题】-C++
  7. 廖雪峰Java1-2Java程序基础-3整数运算
  8. sql中去掉换行符和回车符
  9. 最小生成树之Kruskal算法
  10. iOS 集成银联支付swift