Ada 程式設計/型別/記錄
一個記錄是一個複合型別,它將一個或多個欄位分組在一起。欄位可以是任何型別,甚至可以是記錄。
typeBasic_RecordisrecordA : Integer;endrecord;
空記錄是指當需要一個沒有資料的型別時。有兩種方法可以宣告一個空記錄
typeNull_Recordisrecordnull;endrecord;
typeNull_Recordisnullrecord;
對於編譯器來說,它們是一樣的。但是,程式設計師通常在型別尚未完成時使用第一個變體來表明他們計劃稍後擴充套件該型別,或者他們通常在(帶標記的)記錄是面向物件程式設計中的基類時使用第二個變體。
記錄型別的值可以使用記錄聚合來指定,給出命名的元件列表,如下所示
A_Basic_Record : Basic_Record := Basic_Record'(A => 42); Another_Basic_Record : Basic_Record := (A => 42); Nix :constantNull_Record := (nullrecord);
給定一個稍微大一點的記錄型別,
typeCarisrecordIdentity : Long_Long_Integer; Number_Wheels : Positiverange1 .. 10; Paint : Color; Horse_Power_kW : Floatrange0.0 .. 2_000.0; Consumption : Floatrange0.0 .. 100.0;endrecord;
可以使用位置表示法來指定一個值,也就是說,按宣告順序為每個記錄元件指定一個值
BMW : Car := (2007_752_83992434, 5, Blue, 190.0, 10.1);
但是,命名一個的元件Car聚合提供了許多優勢。
- 輕鬆識別哪個值用於哪個元件。(畢竟,命名元件是記錄存在的根本原因。)
- 允許重新排序元件——你只需要記住元件名稱,而不是它們的位置。
- 改進的編譯器診斷訊息。
可以重新排序元件,因為元件名稱將告知編譯器(以及人類讀者!)預期的值關聯。編譯器訊息的改進也是由於傳遞給編譯器的這些額外資訊的結果。雖然由於 Ada 的覆蓋規則,省略的元件將始終被報告,但是當存在命名關聯時,訊息可以更具體。考慮到Car來自上面的型別,假設程式設計師錯誤地為兩個浮點值中的一個指定了一個值BMW在位置表示法中。編譯器在尋找另一個元件值時,將無法確定指定的值是用於Horse_Power_kW還是用於Consumption. 如果程式設計師使用命名關聯,比如 Horse_Power_kW => 190.0,,則將清楚地知道缺少哪個其他元件。
BMW : Car := (Identity => 2007_752_83992434, Number_Wheels => 5, Horse_Power_kW => 190.0, Consumption => 10.1, Paint => Blue);
為了訪問記錄例項的元件,請使用點分隔符 (.),例如BMW.Number_Wheels.
typeDiscriminated_Record (Size : Natural)isrecordA : String (1 .. Size);endrecord; ... Item : Discriminated_Record := (Size => Value'Length, A => Value);
變體記錄是一種特殊的帶辨別式的記錄,其中某些元件的存在取決於辨別式的值。
typeTraffic_Lightis(Red, Yellow, Green);typeVariant_Record (Option : Traffic_Light)isrecord-- common componentscaseOptioniswhenRed => -- components for redwhenYellow => -- components for yellowwhenGreen => -- components for greenendcase;endrecord;
你可以宣告變體記錄型別,使其辨別式(以及它的變體結構)可以在變數的生命週期內更改。這樣的記錄被稱為可變的。當“改變”記錄時,你必須一次性分配你正在改變的變體結構的所有元件,用完整的變體結構替換記錄。雖然變體記錄宣告可能允許其型別的物件是可變的,但對於物件是否可變有一些限制。限制物件不可變的原因包括
typeTraffic_Lightis(Red, Yellow, Green);typeMutable_Variant_Record (Option : Traffic_Light := Red)is-- the discriminant must have a default valuerecord-- common components Location : Natural;caseOptioniswhenRed => -- components for red Flashing : Boolean := True;whenYellow => -- components for yellow Timeout : Duration := 0.0;whenGreen => -- components for green Whatever : Positive := 1;endcase;endrecord; ... Mutable_Traffic_Light : Mutable_Variant_Record; -- not declaring a discriminant makes this record mutable -- it has the default discriminant/variant -- structure and values Immutable_Traffic_Light : Mutable_Variant_Record (Option => Yellow); -- this record is immutable, the discriminant cannot be changed -- even though the type declaration allows for mutable objects -- with different discriminant values ... Mutable_Traffic_Light := (Option => Yellow, -- mutation requires assignment of all components Location => 54, -- for the given variant structure Timeout => 2.3); ... -- restrictions on objects, causing them to be immutabletypeTraffic_Light_AccessisaccessMutable_Variant_Record; Any_Traffic_Light : Traffic_Light_Access :=newMutable_Variant_Record; Aliased_Traffic_Light :aliasedMutable_Variant_Record;
在堆上分配)
typeTraffic_Lightis(Red, Yellow, Green);typeImmutable_Variant_Record (Option : Traffic_Light)is-- no default value makes the record type immutablerecord-- common components Location : Natural := 0;caseOptioniswhenRed => -- components for red Flashing : Boolean := True;whenYellow => -- components for yellow Timeout : Duration;whenGreen => -- components for green Whatever : Positive := 1;endcase;endrecord; ... Default_Traffic_Light : Immutable_Variant_Record; -- ILLEGAL! Immutable_Traffic_Light : Immutable_Variant_Record (Option => Yellow); -- this record is immutable, since the type declaration is immutable
相反,你可以宣告記錄型別,使辨別式和變體記錄的結構不能更改。要使記錄型別宣告不可變,辨別式不能具有預設值。
聯合typeTraffic_Lightis(Red, Yellow, Green);typeUnion (Option : Traffic_Light := Traffic_Light'First)isrecord-- common componentscaseOptioniswhenRed => -- components for redwhenYellow => -- components for yellowwhenGreen => -- components for greenendcase;endrecord;pragmaUnchecked_Union (Union);pragmaConvention (C, Union); -- optional
此語言功能僅從Ada 2005 開始可用。
與變體記錄的區別在於,Option 實際上並不儲存在記錄中,也不進行正確性檢查 - 它只是一個虛擬的。
這種型別的記錄通常用於與 C 互動,但也可用於其他目的(然後無需 pragma Convention (C, Union);)。
帶標記的記錄pragma Convention (C, Union);typePersonistaggedrecordName : String (1 .. 10); Gender : Gender_Type;endrecord;
typeProgrammerisnewPersonwithrecordSkilled_In : Language_List;endrecord;
帶標記的記錄是其他語言中稱為類的部分。它是Ada 中的面向物件程式設計 的基礎。Ada 中的類還需要另外兩個部分,一個是包,另一個是基本操作。
typeProgrammerisnewPersonandPrintablewithrecordSkilled_In : Language_List;endrecord;
僅限 Ada 2005
抽象帶標記的記錄抽象型別至少有一個抽象基本操作,即它的一個操作沒有定義,並且實現必須由抽象型別的派生型別提供。
帶別名元素[編輯 | 編輯原始碼]如果你來自C/C++,你可能習慣於記錄中的每個元素(不是位集的一部分)都有一個地址。在 Ada 中,情況並非如此,因為記錄與陣列一樣可以打包。與陣列一樣,你可以使用
typeBasic_RecordisrecordA :aliasedInteger;endrecord;
aliased 來確保可以透過訪問型別訪問元素。請注意:每個元素都需要它自己的.
