Ada 编程/类型/受限
当一个类型被声明为limited
这意味着该类型的对象不能被赋值为相同类型的其他对象。一个对象b属于受限类型LT不能被复制到一个对象a属于相同类型。LT.
此外,对于受限类型的对象没有预定义的相等操作。
声明一个受限类型的预期效果包括防止浅复制。此外,对象的(唯一)标识将被保留:一旦声明,变量的名称将继续引用同一个对象。LT以下示例将使用一个相当简单的类型
Boat当我们将一个变量声明为类型.
type
Boatis
limited
private
;function
Choose (Load : Sailors_Units; Speed : Sailors_Units)return
Boat;procedure
Set_Sail (The_Boat :in
out
Boat);
时,它的名称将从那时起表示一条船。船只不会相互复制。当我们将一个变量声明为类型船的完整视图可能被实现为一个记录,例如
该
type
Boatis
limited
record
Max_Sail_Area : Sailors_Units; Max_Freight : Sailors_Units; Sail_Area : Sailors_Units; Freight : Sailors_Units;end
record
;
Choose函数返回一个对象,具体取决于参数当我们将一个变量声明为类型Load和Speed。如果我们现在声明一个类型为 Boat 的变量,我们最好选择一个初始的 Boat(否则我们可能会掉入未初始化的水域!)。但是当我们这样做时,初始化看起来很像赋值,而赋值在受限类型中是不可用的幸运的是,当前的 Ada 区分初始化和复制。受限类型的对象可以通过初始化表达式在分隔符 := 右侧进行初始化。
procedure
Travel (People : Positive; Average_Speed : Sailors_Units)is
Henrietta : Boat := -- assignment? Choose (Load => People * Average_Weight * 1.5, Speed => Average_Speed * 1.5);begin
Set_Sail (Henrietta);end
Travel;
(为了避免混淆:Ada 参考手册区分了赋值和赋值语句,其中赋值是赋值语句的一部分。初始化当然是一种赋值,对于受限类型,它是在原地完成的。赋值语句涉及复制,而复制对于受限类型是禁止的。)
与该特性相关的是 受限类型的聚合体 和受限类型的“构造函数”。在内部,
函数将返回一个受限记录。但是,由于返回类型函数返回一个是受限的,因此任何地方都不允许复制。这会起作用吗?第一次尝试可能是声明一个当我们将一个变量声明为类型result变量局部于,操作函数返回一个,并返回它。该变量局部于对象需要“传输”到调用环境。但是变量局部于是一个局部于变量局部于的变量。当函数返回一个返回时,函数返回一个将不再在范围内。因此看起来变量局部于必须被复制,但这对于受限类型是不允许的。语言提供了两种解决方案:扩展返回语句(参见 6.5:返回语句 [注释])和受限类型的聚合体。以下变量局部于的函数体函数返回一个返回一个受限类型当我们将一个变量声明为类型的聚合体,在找到其组件的初始值后。
function
Choose (Load : Sailors_Units; Speed : Sailors_Units)return
Boatis
Capacity :constant
Sailors_Units := Capacity_Needed (Load);begin
return
Boat' (Max_Freight => Capacity, Max_Sail_Area => Sail_Needed (Capacity), Freight => Load, Sail_Area => 0.0);end
Choose;
返回的对象同时也是要赋予返回值的对象。因此,该函数在Henrietta 中初始化.
。与预定义类型 Ada.Finalization.Controlled类似,Ada 提供了类型Limited_Controlled在同一个包中。它是前者的受限版本。
介绍了几种初始化此类类型的方法。
package
Limited_Private_Samplesis
type
Uninitialisedis
limited
private
;type
Preinitialisedis
limited
private
;type
Dynamic_Initialisationis
limited
private
;function
Constructor (X: Integer) -- any kind of parametersreturn
Dynamic_Initialisation;type
Needs_Constructor (<>)is
limited
private
;function
Constructor (X: Integer) -- any kind of parametersreturn
Needs_Constructor;private
type
Uninitialisedis
record
I: Integer;end
record
;type
Preinitialisedis
record
I: Integer := 0; -- can also be a function callend
record
;type
Voidis
null
record
;function
Constructor (Object:access
Dynamic_Initialisation)return
Void;type
Dynamic_Initialisationis
limited
record
Hook: Void := Constructor (Dynamic_Initialisation'Access
); Bla : Integer; -- any needed componentsend
record
;type
Needs_Constructoris
record
I: Integer;end
record
;end
Limited_Private_Samples;
package
body
Limited_Private_Samplesis
function
Constructor (Object:access
Dynamic_Initialisation)return
Voidis
begin
Object.Bla := 5; -- may be any value only known at run timereturn
(null
record
);end
Constructor;function
Constructor (X: Integer)return
Dynamic_Initialisationis
begin
return
(Hook => (null
record
), Bla => 42);end
Constructor;function
Constructor (X: Integer)return
Needs_Constructoris
begin
return
(I => 42);end
Constructor;end
Limited_Private_Samples;
with
Limited_Private_Samples;use
Limited_Private_Samples;procedure
Tryis
U: 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_Initialisationrenames
Constructor (0); -- already Ada 95 -- I: Needs_Constructor; -- Illegal without initialisation N: Needs_Constructor := Constructor (0); -- Ada 2005 initialisationbegin
null
;end
Try;
请注意,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)