跳转到内容

Ada 编程/类型/受限

来自维基教科书,开放书籍,开放世界

Ada. Time-tested, safe and secure.
Ada.经受时间考验,安全可靠。

受限类型

[编辑 | 编辑源代码]

当一个类型被声明为limited 这意味着该类型的对象不能被赋值为相同类型的其他对象。一个对象b属于受限类型LT不能被复制到一个对象a属于相同类型。LT.

此外,对于受限类型的对象没有预定义的相等操作。

声明一个受限类型的预期效果包括防止浅复制。此外,对象的(唯一)标识将被保留:一旦声明,变量的名称将继续引用同一个对象。LT以下示例将使用一个相当简单的类型

Boat当我们将一个变量声明为类型.

     type Boat is limited private;

     function Choose
       (Load  : Sailors_Units;
        Speed : Sailors_Units)
        return  Boat;

     procedure Set_Sail (The_Boat : in out Boat);

时,它的名称将从那时起表示一条船。船只不会相互复制。当我们将一个变量声明为类型船的完整视图可能被实现为一个记录,例如

     type Boat is limited record
        Max_Sail_Area : Sailors_Units;
        Max_Freight   : Sailors_Units;
        Sail_Area     : Sailors_Units;
        Freight       : Sailors_Units;
     end record;

Choose函数返回一个对象,具体取决于参数当我们将一个变量声明为类型LoadSpeed。如果我们现在声明一个类型为 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  Boat
     is
        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_Samples is

  type Uninitialised  is limited private;
  type Preinitialised is limited private;

  type Dynamic_Initialisation is limited private;
  function Constructor (X: Integer)  -- any kind of parameters
    return Dynamic_Initialisation;

  type Needs_Constructor (<>) is limited private;
  function Constructor (X: Integer)  -- any kind of parameters
    return Needs_Constructor;

private

  type Uninitialised is record
    I: Integer;
  end record;

  type Preinitialised is record
    I: Integer := 0;  -- can also be a function call
  end record;

  type Void is null record;
  function Constructor (Object: access Dynamic_Initialisation) return Void;

  type Dynamic_Initialisation is limited record
    Hook: Void := Constructor (Dynamic_Initialisation'Access);
    Bla : Integer;  -- any needed components
  end record;

  type Needs_Constructor is record
    I: Integer;
  end record;

end Limited_Private_Samples;
package body Limited_Private_Samples is

  function Constructor (Object: access Dynamic_Initialisation) return Void is
  begin
    Object.Bla := 5;  -- may be any value only known at run time
    return (null record);
  end Constructor;

  function Constructor (X: Integer) return Dynamic_Initialisation is
  begin
    return (Hook => (null record),
            Bla  => 42);
  end Constructor;

  function Constructor (X: Integer) return Needs_Constructor is
  begin
    return (I => 42);
  end Constructor;

end Limited_Private_Samples;
 with Limited_Private_Samples;
 use  Limited_Private_Samples;
 
 procedure Try is
 
   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_Initialisation renames Constructor (0);  -- already Ada 95
 
   -- I: Needs_Constructor;  -- Illegal without initialisation
   N: Needs_Constructor := Constructor (0);  -- Ada 2005 initialisation
 
 begin
 
   null;
 
 end Try;

请注意,D3 是一个常量,而其他所有都是变量。

还要注意,为 Preinitialised 的组件定义的初始值是在对象创建时评估的,即,如果使用表达式而不是字面量,则该值可以依赖于运行时。

X, Y: Preinitialised;

在两个对象的这个声明中,初始表达式将被评估两次,并且可以提供不同的值,因为它等效于以下序列:[1]

X: Preinitialised;
Y: Preinitialised;

所以 X 在 Y 之前初始化。

Ada 95 参考手册

[编辑 | 编辑源代码]

Ada 2005 参考手册

[编辑 | 编辑源代码]

Ada 质量和风格指南

[编辑 | 编辑源代码]

参考资料

[编辑 | 编辑源代码]
  1. ISO/IEC 8652:2007. "3.3.1 对象声明 (7)". Ada 2005 参考手册. 任何包含 [...] 多个 defining_identifier 的声明 [...] 等效于一系列声明,每个声明包含列表中的一个 defining_identifier,[...] 顺序与列表相同。 {{cite book}}: Unknown parameter |chapterurl= ignored (|chapter-url= suggested) (help)
华夏公益教科书