在 Ada 中,声明特定的子类型似乎是通用的做法,但为什么呢?

In Ada, it seems to be the general practice to declare specific subtypes, but why?

中,我询问了如何为范围定义无限上限(事实证明答案相当明显,但对于 Ada 新手来说却不是)。在答案中,建议为此创建一个 Specific Subtype

问题中提到的那种特定子类型如下所示:

Type Speed is Float range 0 .. Float'Last

此外,我注意到这个 Ada 项目中的大部分代码都有特定的类型——比如 Feet_FloatMeters_Float 等等。为什么这是首选做法,而不是仅对 class/package?

中的基本 float 成员变量施加范围约束

特定类型的声明有以下好处:

  • 特定类型可防止抽象混合不当。例如,将以米为单位的月球与地球之间的距离除以以欧元表示的比利时国民生产总值。
  • 类型的名称更清楚地记录了类型的预期用途
  • 范围类型的使用清楚地记录了该类型实例的有效值。

Ada 不喜欢子类型 - Ada 程序员喜欢。

新类型和子类型(它们是不同的,并且都有它们的用途)有助于以极低的成本或时间损失捕获如此多的错误,这就是为什么好的类型系统如此过时的一个谜。

例如,认识到任何数组的索引都属于一个子类型(可能是匿名的,但可以像 for i in myArray'range loop ... end loop;subtype myIndextype is myArray'range; theIndex : myIndextype; 中的 myArray'range 一样访问,你会看到在 Ada 中,每个缓冲区溢出漏洞 - 或攻击 - 都只是一个类型错误 - 或者可能是。

当你通过编译器得到一个错误时,当你的可执行文件第一次失败时,一个 Exception : Constraint_Error 指向错误接近错误,你将开始了解范围约束的价值类型。

为了进一步说明这一点,我将参考更多的问答。

首先请注意,您可能使用的编译器 Gnat 可能不严格符合 Ada,除非您如第一个示例中所述在命令行(或项目文件)上添加几个可选标志。最近的版本已经默认打开了其中的一些。

这是一个 subtype being declared, used and going out of visible scope, 的示例(在 declare 块中,其中子类型的范围在运行时之前是未知的。与许多动态类型语言不同,这既快速又安全,因为如果您对实现细节感兴趣,相关存储通常在堆栈上。

还有一个例子

这是not only declaring subtypes but telling the compiler how to pack them in storage的一个极端例子。在嵌入式编程中很常见,在 space 很紧的情况下(我在具有 1kbyte 内存的处理器中有一个完整的数字手表!)或用于访问硬件寄存器中的特定位。 (请注意,如果更新为使用 Ada-2012 aspects,此示例会更清晰。)

此问答简要介绍了 ,来自 Java。 (我有点失望 none 的 Java 专家在关闭之前管理了一个答案,描述了他们将如何处理相同的问题)

Ada 中的范例是在解决方案中模拟问题。其中一方面是使用适当的标量类型和子类型定义对问题 space 中值的范围、准确度和精确度进行建模。

为什么要这样做? McCormick 在分析为什么有 C 经验而没有 Ada 经验的学生能够完成他的实时 S/W 课程项目时,Ada 而不是 C 发现 Ada 最重要的特性是

Modeling of scalar objects.

  • Strong typing.
  • Range constraints.
  • Enumeration types.

McCormick's paper

McCormick's site