程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> Delphi >> Delphi的語法詳細示例

Delphi的語法詳細示例

編輯:Delphi

在 Design Patterns 書中談及 Parameterized Types,做法上著名的有 C++ 的 Templates 及 Ada、Eiffel 的 generics,其中又談到「這種技術讓你只定義一種型態而無須指定程序會使用到的所有型態」(原文為:This technique lets you define a type without specifying all the other types it uses),這做何解釋?有感當日盈學兄詢問我時,答得不夠清楚,因此於此做些補充。

首先從C++ 的 Templates 說起,Kaare Christian 於 1994/01/25 的一篇文章中點出 Templates 的重點,並說得生動有趣。以下為其說明的片段,翻譯如下:

無性生殖並不只存於遺傳工程,對程序員而言,它也是一種由來已久的動作。過去,我們只不過使用一個簡單的基本工具,也就是文字編輯器,透過剪貼的方式重制(朱子注:復制後做局部的修改)程序代碼。今天,C++ 提供我們一個更好的繁殖方法: Template。

復制一段既有程序代碼,最平常的一個理由就是:為了改變數據型態(朱子注:作者的說法是比較主觀些,但重點不在這裡)。舉個例子,假設你寫一個繪圖函式,使用型態為 Long 的 X、Y 坐標﹔突然之間你需要相同的算法,但坐標改采用 float 型態。當然你可以使用一個文字編輯器將這段程序代碼復制一份,然後修改坐標值其中的數據型態。甚至你也可以使用C++ 的 overloaded functions,那麼就可以繼續使用相同的函式名稱。Function Overloading 的確可以使我們的程序看起來比較清爽,但是你仍舊必須在程序的許多地方維護完全相同的程序代碼。

(省略)

Templates 提供比較好的解決方案,它將「一般性算法」和其它「對數據型態的實際系結」區分開來。你可以先寫出算法的程序代碼,使用時才填入實際的數據型態。C++ 的 Templates 使「數據型態」也可以用參數的方式出現。有了 Template,我們可以擁有 Macros (朱子注:C 的宏語法)「只寫一次」的優點,以及overloaded functions「型態檢驗」的優點。

我現在舉個 Template Functions 的例子,有一個計算次方的函式,名為 Power(),對於 int 數據型態的函式以 C++ 的語法來寫如下:

int power(int base, int exp){

int result = base;

if (exp == 0) return (int) 1;

if (exp < 0) return (int) 0;

while (--exp) result *= base;

return result;}

對於 long 數據型態的函式以 C++ 的語法來寫如下:

long power(long base, int exp){

long result = base;

if (exp == 0) return (long) 1;

if (exp < 0) return (long) 0;

while (--exp) result *= base;

return result;}

對於 float 及其它數據型態的函式也是只要復制以上函式後,改變相關數據型態即可,然很我們從以上的例子可以清楚的看到,必須對不同的數據型態撰寫相同算法的程序代碼。若改用 Template 寫法又如何?以 C++ 的 Template 語法來改寫如下:

template <class T>

T power(T base, int exp){

T result = base;

if (exp == 0) return (T) 1;

if (exp < 0) return (T) 0;

while (--exp) result *= base;

return result;}

如此,我們無須在編輯時期特別定義 T 為何種特定的數據型態,而延遲至程序執行階段呼叫此函式時,才決定它應該是什麼數據型態。例如:

void main(){

int i = power(5, 4) // 結果為 i=625,數據型態 T 為 int

long l = power(1000L, 3) // 結果為 l=1000000000,數據型態 T 為 long

// 以此類推}

Template Classes 亦大致如此,於此不再贅言。Ada、Eiffel 的 generics 也是類似這樣處理,你們可以參考 Building Application Frameworks 書中第 334 頁 Figure 14.7。

然而 Object Pascal (包含 JavaSmalltalk)並沒有 Template 這類的語法,所以我回答盈學兄有關 Parameterized Types 時所舉的范例並不是恰如其分,所以讓盈學兄感到莫名不已,然而也並非說我所舉的例子不正確,因為對 Object Pascal 而言,這是最恰當的說明。因為大部分 Template Classes 的范例都是用來當作 Container Classes。C++ 有一套標准的 Template 鏈接庫(Standard Template Library:STL),共有六種主要部分,分別為 Containers、Generic Algorithms、Iterators、Function objects、Adaptors、Allocators,而 Microsoft Foundation Classes 也有一組 Collection Classes,作用與 STL 相同。Delphi 內的 TListTCollectionTStringList 等也是屬於 Container Classes,而它們皆繼承來自 TObject

想想看吧!Template 或 Generic 與「虛擬及多型」的關系?多了解一些 RTTI(Runtime Type Information)如何?

**************************************************************************

執行期及編譯期的結構關系

OO程序在執行期結構有點類似他的程序代碼結構,程序代碼結構在編譯期即已固定;它包含固定的階層類關系,程序的執行期結構包含對象間快速改變的溝通網絡。事實上此二者是互相關聯的。

考慮對象間的結合(aggregate)與認識(acquaintance)及他們在執行期與編譯期間如何以不同方式顯示(manifest)他們。復合(aggregate)代表為其它對象所擁有或必須對其他對象負責,一般稱作一個對象有(heaving)其它對象或是其它對象的部分。復合亦即表示一個復合對象及他的擁有者有共同的生命周期。認識(acquaintance)只是代表一個對象被另一個對象所了解(knows of);有時了解稱作協合(association)或使用(using)的關系,認識對象向其它對象的操作提出請求;但他們並不義務為其它對象作任何事。認識關系是比結合較弱的關系並且提供對象間松散的配對(coupling)關系。兩者圖形表示如下:

結合者(aggregator)

被結合者(aggregatee)

結合關系

aggregateinstance

認識者(acquaintor)

被認識者(acquaintee)

認識關系

acquainteinstance


此兩者很容易被混淆;因為他們以相同的方式實現。C++的結合關系可以定義實例的成員變量;但最好是定義成實例的指針或參考,認識關系也是定義實例的指針或參考。結合及認識關系一般是依據其目的(intent)多於其語言機制(language mechanisms)。兩者的在編譯期的差異並不明顯但是很重要的。結合關系比認識關系多傾向於比較少的關聯(relationship)而不變的(permanent)。認識關系常常在執行當中被產建立及再建立;有時只存在一個操作(Operation)當中,所以是比較動態的;有時難與從程序代碼中辨識出來。

由於執行期及編譯期的差異;所以從程序代碼無法顯示有關系統如何執行的所有狀況。所以系統的執行期結構必須由設計師決定更甚於程序語言。對象及其型別的關系必須小心的設計;因為其決定執行期結構的好壞。

許多模式(特別是那些有對象范圍(scope)關系的)會區分執行祈雨編譯期結構的差異的。復合(Composite)裝飾者(Decorator)尤其是對於建立復雜的執行期結構特別有用。觀察者(Observer)結合的執行期結構往往難以了解除非你對於這個模式非常熟悉。責任鏈(Chain of Responsibility)也是交談模式的一種結果;在繼承關系並不是明顯的。一般而言執行期結構是難以從程序代碼中去了解的除非你了解模式。

設計容易改變的系統(Designing for Change)

設計最大可再使用的關鍵在於新的需求及對於現存需求改變的預測;及設計你的系統讓它可以持續發展。要設計一套強固的系統以應付改變你必須考慮在系統的生命周期必須的改變。這些改變包括類的重新定義及重新實現、客戶的修改及重新測試。再設計影響軟件系統需多部分及無法預期的改變必然耗費成本的。模式協助你讓系統可以特殊的方式更新以避免這些問題。每一種模式讓某些系統結構觀點(ASPect)可以獨立改變;因此讓系統更強固應付某些種類的改變。

1. 以明確的定義類來建立對象(Creating an object by specifying a class explicility):當你要建立一個對象來完成你特定的實現時先定義一個類名稱;而非特定的界面。這個實現可能使未來的改變復雜化;要避免這樣最好間接的建立你的對象。

相關的模式:抽象工廠(Abstract Factory)、工廠方法(Factory Method)、原型(Prototype)

2. 特定的操作的相依性(Dependence on specific Operation):當定義一個特定的操作時你要讓只是滿足一個請求。經由避免硬寫(hard-coded)以滿足請求;你可以容易的方式滿足需求改變在執行期及編譯期。

相關的模式:責任鏈(Chain of Responsibility)、指令(Command)

3. 硬件及軟件平台的相依性(Dependence on hardware and software platform):外在的操作系統接口及應用程序接口(APIs)在不同的硬件及軟件平台是不同的,軟件相依於一特定平台難以移植至其它平台;甚至相同平台的不同版本也難以移植。所以如何讓你的設計不相依於平台是重要的。

相關的模式:抽象工廠(Abstract Factory)、建設者(Builder)

4. 對象的顯示或實現的相依性(Dependence on object representations or implementations)當一個對象的改變時;使用這個對象的客戶所了解的此對象的顯示(represented)、儲存(stored)、位置(located)或實現(implemented)可能必須隨之改變。隱藏這些信息可以讓改變不至於關聯太大(keep changes from cascading)。

相關的模式:抽象工廠(Abstract Factory)、建設者(Builder)、備忘錄(Memento)、代理(Proxy)

5. 算法的相依性(Algorithmic dependencIEs)算法往往是廣泛的(extent)、最佳化的(optimized);在發展時取代及重復使用。對象若相依於某一算法時;在算法一修改則必須相對修改。因此算法的修改必須隔離。

相關的模式:橋接(Bridge)、迭代(Iterator)、策略(Strategy)、模板方法(Template Method)、訪問者(Visitor)

6. 緊密的鏈接關系(Tight coupling)類若緊密的鏈接責難以獨立再使用因為他們互相依賴。若你不了解整體責難已改變或移動任一類;以致於難以了解、分割及維護。模式使用抽象鏈接(abstract coupling)及層級(layering)的技術來實現松散鏈接(loosely coupling)系統。

相關的模式:抽象工廠(Abstract Factory)、橋接(Bridge)、責任鏈(Chain of Responsibility)、指令(Command)、外觀(Facade)、備忘錄(Memento)、觀察者(Observer)

7. 以繼承擴充功能(Extending functionality by subclassing)以繼承來制作對象往往並不是那麼容易的。每一個新類都有固定的實現成本(overhead)(例如initialization、finalization等),定義一個子類也必須深度了解其父類。例如覆蓋(overriding)一個操作可能也必須覆蓋另一個。一個覆蓋操作可能必須呼叫繼承操作。有時使用繼承方式可能使你的類暴增。對象復合及委托彈性的提供使用繼承替代方式來復合行為。應用系統新的功能可以利用復合現有的對象來達成而非定義新的類。但是從另一個觀點過分使用對象復合可能使的系統難以了解。許多模式可以提供你定義一個新的子類並與現存的對象復合以產生新的功能。

相關的模式:橋接(Bridge)、責任鏈(Chain of Responsibility)、復合(Composite)、裝飾者(Decorator)、觀察者(Observer)、策略(Strategy)

8. 無法方便的修改類(Inability to alter classes convenIEntly)有時你希望去修改一個類但是卻沒有辦法;其原因可能是你沒有原始碼,或者必須同時去修改一堆現存的子類。模式提供你修改的方法。

相關的模式:適配器(Adapter)、裝飾者(Decorator)、訪問者(Visitor)

模式運用的三個領域:應用程序(application Programs)、工具程序(Toolkits)、框架(Frameworks)

應用程序:略

工具程序:略

框架:框架是一組相互合作的類為一軟件的特殊類組成再使用的設計。框架規范(dictates)你系統的架構(architecture);它定義所有的結構(structure);然後劃分成類及對象,因此它的重要責任是類及對象間如何合作及控制的流程(thread)。框架事先定義參予的組件讓你的架構在你的應用系統中。框架撷取應用系統領域中共通原則的設計決策。框架強調的是設計再使用(design reuse)而非程序代碼再使用(code reuse);因此框架一般包括具體的子類讓你立即可以加入使用。

此一層次的再使用導致介於以此為基礎的應用系統及軟件間的反向控制(inversion of control)。例如你使用工具程序(toolkit)你是先寫應用程序的主體再呼叫你要再使用的程序代碼,反之使用框架你是再使用主體再寫下它呼叫的程序代碼,因此你必須先寫操作並給於特定名稱及呼叫的協議(conventions)。這樣可以減少你在設計時的決策。

框架的好處是可以快速構建應用系統;同時這些系統都可以有類似的結構。這種方式所構建的系統容易維護同時對使用者提供一致性的外觀及操作。缺點是你缺乏構建的自由度因為許多設計決策已事先就決定了。

應用程序、工具程序、框架三者中框架是最難設計的。框架設計者的風險是要設計一個架構符合領域中所有的應用程序。任何對框架設計的修改將減少它的利益,因為框架的主要貢獻是它所定義的架構。因此在設計框架時必須盡可能使它擁有足夠的彈性及擴充性。其次;因為應用系統是相當依賴框架所以對於框架的接口的修改是非常敏感的。所以松散戀結是非常重要的。

框架設計采用模式可以改善上述框架設計的問題,成熟的框架一般都是使用模式。另一個采用模式的優點是使用模式的文件來產生框架的文件。使用者若熟悉模式那麼對於框架便更容易上手。若使用者不熟悉模式則在學習框架時便可以同時從框架的文件中了解模式。框架一般在使用上有一段相當陡的學習曲線;雖然模式也不是平緩的學習曲線;但可以經由框架設計組件更精確以減緩使用上的學習曲線。

模式與框架頗為類似;其不同點有三:

1. 模式比框架更抽象:框架以程序代碼為主體(embody);而模式只有范例是程序代碼。

2. 相對框架;模式是比較小的架構元素(architectural):框架可包含多個模式;反之則否。

3. 相較框架;模式是比較不特定的:框架一般屬於特定領域的應用;模式則可以應用於所有領域。

框架的應用愈來愈普遍也愈來愈重要。它是OO達成再使用的一種方式;大型的OO應用系統以不同層次的框架來互動。需多的應用系統設計將來自框架並受其影響。

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