通过强类型和运算符重载进行简单的单元检查
naive unit checking via strong typing and operator overloading
我正在阅读有关 strong typing in Ada focused on units checking 的内容,并决定自己测试这种幼稚的方法:
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) 中我们有
... The name or prefix shall not resolve to denote an abstract subprogram unless it is also a dispatching subprogram.
和 Meters
不是标记类型,因此 "*"
不是调度。
你也可以声明一个非重载的子程序abstract
:
function "and" (Left, Right : Meters) return Meters
is abstract;
GNAT 说 cannot call abstract subprogram "and"
,因为 ARM 3.9.3(7)。
我正在阅读有关 strong typing in Ada focused on units checking 的内容,并决定自己测试这种幼稚的方法:
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) 中我们有
... The name or prefix shall not resolve to denote an abstract subprogram unless it is also a dispatching subprogram.
和 Meters
不是标记类型,因此 "*"
不是调度。
你也可以声明一个非重载的子程序abstract
:
function "and" (Left, Right : Meters) return Meters
is abstract;
GNAT 说 cannot call abstract subprogram "and"
,因为 ARM 3.9.3(7)。