Ada 编程/类型/记录
一个记录是一个复合类型,它将一个或多个字段分组在一起。字段可以是任何类型,甚至可以是记录。
type
Basic_Recordis
record
A : Integer;end
record
;
空记录是指当需要一个没有数据的类型时。有两种方法可以声明一个空记录
type
Null_Recordis
record
null
;end
record
;
type
Null_Recordis
null
record
;
对于编译器来说,它们是一样的。但是,程序员通常在类型尚未完成时使用第一个变体来表明他们计划稍后扩展该类型,或者他们通常在(带标记的)记录是面向对象编程中的基类时使用第二个变体。
记录类型的值可以使用记录聚合来指定,给出命名的组件列表,如下所示
A_Basic_Record : Basic_Record := Basic_Record'(A => 42); Another_Basic_Record : Basic_Record := (A => 42); Nix :constant
Null_Record := (null
record
);
给定一个稍微大一点的记录类型,
type
Caris
record
Identity : Long_Long_Integer; Number_Wheels : Positiverange
1 .. 10; Paint : Color; Horse_Power_kW : Floatrange
0.0 .. 2_000.0; Consumption : Floatrange
0.0 .. 100.0;end
record
;
可以使用位置表示法来指定一个值,也就是说,按声明顺序为每个记录组件指定一个值
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.
type
Discriminated_Record (Size : Natural)is
record
A : String (1 .. Size);end
record
; ... Item : Discriminated_Record := (Size => Value'Length, A => Value);
变体记录是一种特殊的带辨别式的记录,其中某些组件的存在取决于辨别式的值。
type
Traffic_Lightis
(Red, Yellow, Green);type
Variant_Record (Option : Traffic_Light)is
record
-- common componentscase
Optionis
when
Red => -- components for redwhen
Yellow => -- components for yellowwhen
Green => -- components for greenend
case
;end
record
;
你可以声明变体记录类型,使其辨别式(以及它的变体结构)可以在变量的生命周期内更改。这样的记录被称为可变的。当“改变”记录时,你必须一次性分配你正在改变的变体结构的所有组件,用完整的变体结构替换记录。虽然变体记录声明可能允许其类型的对象是可变的,但对于对象是否可变有一些限制。限制对象不可变的原因包括
type
Traffic_Lightis
(Red, Yellow, Green);type
Mutable_Variant_Record (Option : Traffic_Light := Red)is
-- the discriminant must have a default valuerecord
-- common components Location : Natural;case
Optionis
when
Red => -- components for red Flashing : Boolean := True;when
Yellow => -- components for yellow Timeout : Duration := 0.0;when
Green => -- components for green Whatever : Positive := 1;end
case
;end
record
; ... 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 immutabletype
Traffic_Light_Accessis
access
Mutable_Variant_Record; Any_Traffic_Light : Traffic_Light_Access :=new
Mutable_Variant_Record; Aliased_Traffic_Light :aliased
Mutable_Variant_Record;
在堆上分配)
type
Traffic_Lightis
(Red, Yellow, Green);type
Immutable_Variant_Record (Option : Traffic_Light)is
-- no default value makes the record type immutablerecord
-- common components Location : Natural := 0;case
Optionis
when
Red => -- components for red Flashing : Boolean := True;when
Yellow => -- components for yellow Timeout : Duration;when
Green => -- components for green Whatever : Positive := 1;end
case
;end
record
; ... 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
相反,你可以声明记录类型,使辨别式和变体记录的结构不能更改。要使记录类型声明不可变,辨别式不能具有默认值。
联合type
Traffic_Lightis
(Red, Yellow, Green);type
Union (Option : Traffic_Light := Traffic_Light'First)is
record
-- common componentscase
Optionis
when
Red => -- components for redwhen
Yellow => -- components for yellowwhen
Green => -- components for greenend
case
;end
record
;pragma
Unchecked_Union (Union);pragma
Convention (C, Union); -- optional
此语言功能仅从Ada 2005 开始可用。
与变体记录的区别在于,Option 实际上并不存储在记录中,也不进行正确性检查 - 它只是一个虚拟的。
这种类型的记录通常用于与 C 交互,但也可用于其他目的(然后无需 pragma
Convention (C, Union);
)。
带标记的记录pragma
Convention (C, Union);type
Personis
tagged
record
Name : String (1 .. 10); Gender : Gender_Type;end
record
;
type
Programmeris
new
Personwith
record
Skilled_In : Language_List;end
record
;
带标记的记录是其他语言中称为类的部分。它是Ada 中的面向对象编程 的基础。Ada 中的类还需要另外两个部分,一个是包,另一个是基本操作。
type
Programmeris
new
Personand
Printablewith
record
Skilled_In : Language_List;end
record
;
仅限 Ada 2005
抽象带标记的记录抽象类型至少有一个抽象基本操作,即它的一个操作没有定义,并且实现必须由抽象类型的派生类型提供。
带别名元素[编辑 | 编辑源代码]如果你来自C/C++,你可能习惯于记录中的每个元素(不是位集的一部分)都有一个地址。在 Ada 中,情况并非如此,因为记录与数组一样可以打包。与数组一样,你可以使用
type
Basic_Recordis
record
A :aliased
Integer;end
record
;
aliased
来确保可以通过访问类型访问元素。请注意:每个元素都需要它自己的
.