Ada 程式設計/型別/受限
當一個型別被宣告為limited 這意味著該型別的物件不能被賦值為相同型別的其他物件。一個物件b屬於受限型別LT不能被複制到一個物件a屬於相同型別。LT.
此外,對於受限型別的物件沒有預定義的相等操作。
宣告一個受限型別的預期效果包括防止淺複製。此外,物件的(唯一)標識將被保留:一旦宣告,變數的名稱將繼續引用同一個物件。LT以下示例將使用一個相當簡單的型別
Boat當我們將一個變數宣告為型別.
typeBoatislimitedprivate;functionChoose (Load : Sailors_Units; Speed : Sailors_Units)returnBoat;procedureSet_Sail (The_Boat :inoutBoat);
時,它的名稱將從那時起表示一條船。船隻不會相互複製。當我們將一個變數宣告為型別船的完整檢視可能被實現為一個記錄,例如
該
typeBoatislimitedrecordMax_Sail_Area : Sailors_Units; Max_Freight : Sailors_Units; Sail_Area : Sailors_Units; Freight : Sailors_Units;endrecord;
Choose函式返回一個物件,具體取決於引數當我們將一個變數宣告為型別Load和Speed。如果我們現在宣告一個型別為 Boat 的變數,我們最好選擇一個初始的 Boat(否則我們可能會掉入未初始化的水域!)。但是當我們這樣做時,初始化看起來很像賦值,而賦值在受限型別中是不可用的幸運的是,當前的 Ada 區分初始化和複製。受限型別的物件可以透過初始化表示式在分隔符 := 右側進行初始化。
procedureTravel (People : Positive; Average_Speed : Sailors_Units)isHenrietta : Boat := -- assignment? Choose (Load => People * Average_Weight * 1.5, Speed => Average_Speed * 1.5);beginSet_Sail (Henrietta);endTravel;
(為了避免混淆:Ada 參考手冊區分了賦值和賦值語句,其中賦值是賦值語句的一部分。初始化當然是一種賦值,對於受限型別,它是在原地完成的。賦值語句涉及複製,而複製對於受限型別是禁止的。)
與該特性相關的是 受限型別的聚合體 和受限型別的“建構函式”。在內部,
函式將返回一個受限記錄。但是,由於返回型別函式返回一個是受限的,因此任何地方都不允許複製。這會起作用嗎?第一次嘗試可能是宣告一個當我們將一個變數宣告為型別result變數區域性於,操作函式返回一個,並返回它。該變數區域性於物件需要“傳輸”到呼叫環境。但是變數區域性於是一個區域性於變數區域性於的變數。當函式返回一個返回時,函式返回一個將不再在範圍內。因此看起來變數區域性於必須被複制,但這對於受限型別是不允許的。語言提供了兩種解決方案:擴充套件返回語句(參見 6.5:返回語句 [註釋])和受限型別的聚合體。以下變數區域性於的函式體函式返回一個返回一個受限型別當我們將一個變數宣告為型別的聚合體,在找到其元件的初始值後。
functionChoose (Load : Sailors_Units; Speed : Sailors_Units)returnBoatisCapacity :constantSailors_Units := Capacity_Needed (Load);beginreturnBoat' (Max_Freight => Capacity, Max_Sail_Area => Sail_Needed (Capacity), Freight => Load, Sail_Area => 0.0);endChoose;
返回的物件同時也是要賦予返回值的物件。因此,該函式在Henrietta 中初始化.
。與預定義型別 Ada.Finalization.Controlled類似,Ada 提供了型別Limited_Controlled在同一個包中。它是前者的受限版本。
介紹了幾種初始化此類型別的方法。
packageLimited_Private_SamplesistypeUninitialisedislimitedprivate;typePreinitialisedislimitedprivate;typeDynamic_Initialisationislimitedprivate;functionConstructor (X: Integer) -- any kind of parametersreturnDynamic_Initialisation;typeNeeds_Constructor (<>)islimitedprivate;functionConstructor (X: Integer) -- any kind of parametersreturnNeeds_Constructor;privatetypeUninitialisedisrecordI: Integer;endrecord;typePreinitialisedisrecordI: Integer := 0; -- can also be a function callendrecord;typeVoidisnullrecord;functionConstructor (Object:accessDynamic_Initialisation)returnVoid;typeDynamic_InitialisationislimitedrecordHook: Void := Constructor (Dynamic_Initialisation'Access); Bla : Integer; -- any needed componentsendrecord;typeNeeds_ConstructorisrecordI: Integer;endrecord;endLimited_Private_Samples;
packagebodyLimited_Private_SamplesisfunctionConstructor (Object:accessDynamic_Initialisation)returnVoidisbeginObject.Bla := 5; -- may be any value only known at run timereturn(nullrecord);endConstructor;functionConstructor (X: Integer)returnDynamic_Initialisationisbeginreturn(Hook => (nullrecord), Bla => 42);endConstructor;functionConstructor (X: Integer)returnNeeds_Constructorisbeginreturn(I => 42);endConstructor;endLimited_Private_Samples;
withLimited_Private_Samples;useLimited_Private_Samples;procedureTryisU: Uninitialised; -- very bad P: Preinitialised; -- has initial value (good) D1: Dynamic_Initialisation; -- has initial value (good) D2: Dynamic_Initialisation := Constructor (0); -- Ada 2005 initialisation D3: Dynamic_InitialisationrenamesConstructor (0); -- already Ada 95 -- I: Needs_Constructor; -- Illegal without initialisation N: Needs_Constructor := Constructor (0); -- Ada 2005 initialisationbeginnull;endTry;
請注意,D3 是一個常量,而其他所有都是變數。
還要注意,為 Preinitialised 的元件定義的初始值是在物件建立時評估的,即,如果使用表示式而不是字面量,則該值可以依賴於執行時。
X, Y: Preinitialised;
在兩個物件的這個宣告中,初始表示式將被評估兩次,並且可以提供不同的值,因為它等效於以下序列:[1]
X: Preinitialised; Y: Preinitialised;
所以 X 在 Y 之前初始化。
- ↑ ISO/IEC 8652:2007. "3.3.1 物件宣告 (7)". Ada 2005 參考手冊.
任何包含 [...] 多個 defining_identifier 的宣告 [...] 等效於一系列宣告,每個宣告包含列表中的一個 defining_identifier,[...] 順序與列表相同。
{{cite book}}: Unknown parameter|chapterurl=ignored (|chapter-url=suggested) (help)
