Ada語言寶書課程#3:Ada 2005 受限型別— 建構函式
寶書課程 #3: Ada 2005 受限型別— 建構函式
by Bob Duff—AdaCore
Translator:Dongfeng.Gu
讓我們開始…
考慮到Ada2005允許受限型別的現場集合(宣告),下一步顯然是要將這樣的集合包裝到抽象中--有名的,從函式返回它們。畢竟,有趣的型別通常是私有的,我們也需要一些方法讓客戶端建立和初始化物件。
package P is
type T (<>) is limited private
function Make_T (Name : String) return T; – constructor function
private
type T is limited
record
Name : Unbounded_String;
My_Task : Some_Task_Type;
My_Prot : Some_Protected_Type;
end record;
end
package body P is
function Make_T (Name : String) return T is
begin
return (Name => To_Unbounded_String (Name), others => <>);
end Make_T;
end P;
在Ada95中,受限型別不能允許有建構函式(就是函式建立新物件並返回它們)。Ada2005則允許完全通用的建構函式。鑑於上述,客戶端可以這樣說:
My_T : T := Make_T (Name => "Bartholomew Cubbins");
對於集合,Make_T的結果是現場生成的(就是在My_T物件中),而不是先建立而後複製到My_T中增加另一層次的函式呼叫,我們可以這樣做:
function Make_Rumplestiltskin return T is
begin
return Make_T (Name => “Rumplestiltskin”);
end Make_Rumplestiltskin;
Rumplestiltskin_Is_My_Name : constant T := Make_Rumplestiltskin;
這可能有助於理解實現模型:在這種情況下,Ruplestaltskin _ Is _ My _ Name是以通常的方式分配的(在棧上,假設它被宣告到某個子程式的本地)。它的地址作為一個額外的隱式引數傳遞給Make_Rumplestaltskin,然後將相同的地址傳遞給Make_T,接著在那個地址現場建立集合。受限物件絕對不能被拷貝!在這種情況下,Make_T將初始化成員Name,並建立My_Task和My_Prot成員,所有這些成員都直接(被建立)在Ruplestaltskin_Is_My_Name中。
注意Rumplestiltskin_Is_My_Name是個常量。在Ada95中,無法建立一個常量的受限物件,因為沒有初始化(受限物件)的方法。
類似於在Ada95中,型別T中的“(<>)”意思是從客戶端角度看它有“未知的判別式”。這是一個防止客戶端建立預設初始化物件的技巧(就是,“X:t;”是非法的)。因此,客戶端每當建立T型別物件的時候必須呼叫Make_T,給與包P對於初始化物件的完全控制。
理想情況下,受限型別和非受限型別應該是相同的,除了本質區別:你不能複製受限物件。Ada2005中允許受限型別的函式與集合使我們非常接近這個目標。一些語言有一個特殊的特徵叫做建構函式。在Ada中,建構函式就是一個建立新物件的函式。除了在Ada95中,這僅用於非受限型別。對於受限型別,唯一的實現建構函式的方法是通過預設值的宣告,這將把你限制在一個建構函式中。將引數傳遞給該建構函式的唯一方法是通過判別式。在Ada2005中,我們可以說:
This_Set : Set := Empty_Set;
That_Set : Set := Singleton_Set (Element => 42);
Set是否受限,語句“This_Set : Set := Empty_Set;” 對於我來說看起來比如下語句更清楚:
This_Set : Set;
(該語句)這可能意味著“預設初始化為空Set”或者可能意味著“暫時先不初始化,我們之後再初始化它”。