ada - 通过强类型和运算符重载进行简单的单元检查
问题描述
我正在阅读Ada 中关于单元检查的强类型化,并决定自己测试这种幼稚的方法:
procedure Example is
type Meters is new Float;
type Meters_Squared is new Float;
function "*" (Left, Right : Meters) return Meters_Squared is
begin
return Meters_Squared(Float(Left)*Float(Right));
end;
len_a : Meters := 10.0;
len_b : Meters := 15.0;
surface : Meters_Squared;
len_sum : Meters;
begin
len_sum := len_a + len_b; -- ok
surface := len_a * len_b; -- ok
len_sum := len_a * len_b; -- invalid
end Example;
现在我知道这实际上不是实用的方法,我正在尝试这只是作为一种学习经验。根据我到目前为止的尝试,我一定遗漏了一些东西,因为当我尝试编译上面列出的示例时,我没有收到任何错误:
$ make example
gcc -c example.adb
gnatmake example.adb
gnatbind -x example.ali
gnatlink example.ali
当我删除重载乘法运算符的函数定义时,它会按预期失败:
$ make example
gcc -c example.adb
example.adb:14:20: expected type "Meters_Squared" defined at line 3
example.adb:14:20: found type "Meters" defined at line 2
make: *** [Makefile:6: example] Error 1
考虑到这一点,我不明白,在乘法运算符重载的情况下,编译器如何可以surface := len_a * len_b
同时len_sum := len_a * len_b
使用。
解决方案
您的"*"
重载就是这样;Meters
继承
function "*" (Left, Right: Meters) return Meters;
从Float
.
你可以做的是抑制继承的功能:
function "*" (Left, Right: Meters) return Meters
is abstract;
在这种情况下,标记不需要的函数abstract
会将其从重载解决方案的考虑中移除:在ARM 6.4(8)中,我们有
...名称或前缀不应解析为表示抽象子程序,除非它也是一个调度子程序。
并且Meters
不是标记类型,所以"*"
不是调度。
您还可以声明一个非重载的子程序abstract
:
function "and" (Left, Right : Meters) return Meters
is abstract;
GNAT 说cannot call abstract subprogram "and"
,因为 ARM 3.9.3(7)。
推荐阅读
- curl - 是否有可能在 nifi 处理器中添加敏感字段?
- javascript - Object 构造函数是如何出现在任何函数的原型对象中的?
- woocommerce - 如果将两个或三个产品一起添加到购物车中,则更改它们的价格。电子商务
- python - 如何将数据框行检查为字符串?
- python - why autoencoder tutorial of pytorch changes the view of embedding layer output?
- python - 填充数据框的列
- javascript - 拦截真实数据响应
- python - 你如何让 Discord 机器人响应 DM 中的命令?(Python)
- flutter - 在 Android 页面启动时立即调用 flutter_local_notifications 的 onSelectNotification 方法(在 iOS 中没有此类问题)
- android - NullPointerException:尝试在空对象引用上调用虚拟方法“void SettingsFragment.loadFromSharedPreferences()”