埃菲尔的附加声明中的局部变量的重点是什么?

时间:2016-05-06 20:36:53

标签: void eiffel void-safety

在Eiffel中,Void Safety是一种静态防止取消引用未初始化(" null")对象的方法。它的工作方式是首先,必须将对象声明为 detachable ,然后你需要检查if-block是否实际上附加(即在你使用它之前有一些价值。

这是我到目前为止使用它的方式:

some_object: detachable TYPE

...

if attached some_object then
  some_object.method
end

完全正常工作:没有附加检查,编译失败并且#34; Object_call的目标可能无效"错误。 然而,在真正阅读了关于虚拟安全的documentation后,我了解到这实际上是它应该是这样的:

some_object: detachable TYPE

...

if attached some_object as l_some_object then
  l_some_object.method
end

在这种形式中,l_some_object是if-block 的本地变量,它指向与some_object相同的对象,但在静态上保证是非空的。

但是,我没有看到这个as-clause存在的原因。正如我在上面指出的那样,显然原始的some_object已经在if-block中被静态保证为非空,那么引入另一个变量的重点是什么?

除了范围之外,some_objectl_some_object之间有什么区别?

1 个答案:

答案 0 :(得分:4)

简短回答

如果some_object是局部变量,则没有必要引入对象测试本地l_some_object

答案很长

对象测试的一般形式是

attached {SOME_TYPE} expr as var

其中{SOME_TYPE}var是可选的。如果未使用类型(上例中的{SOME_TYPE}),则对象测试只会检查是否附加了expr,并在附加时将其值分配给var

理论上可以预期以下类似的东西是无效的:

if attached expr then
    expr.do_something
end

但是在一般情况下不允许这样做,因为expr可能有副作用,所以第二次计算它时会返回一个不同的值,而这个值可能是void来制作代码空隙不安全:

if attached foo then -- On first call function foo returns non-void value.
    foo.do_something -- On second call function foo returns void: BOOM!
end

另一种可能性是改变表达式值的中间调用,例如

if attached attr then -- Attribute attr is attached here.
    bar               -- bar sets attr to Void.
    attr.do_something -- BOOM!
end

如果bar将属性attr设置为void(这可以间接完成),则代码将再次无效 -

最后在多线程环境中,另一个线程可能会在检查之后以及在#34;然后使用之前更改attr的值。部分甚至没有任何中间功能调用:

if attached attr then -- Attribute attr is attached here.
                      -- Another thread sets attr to Void.
    attr.do_something -- BOOM!
end

为防止出现这些情况,请使用var部分。此对象测试local是只读的,不受任何中间功能调用或其他线程对同一表达式的评估的影响。换句话说,它始终是附加的。

在某些情况下,对象测试表达式不受这些因素的影响:

  1. 参数是只读的,因此使用短格式

    总是足够的
    attached arg
    

    并且将对象测试引入本地是没有意义的,因为它总是等于参数。

  2. 如果为局部变量和Result分配了可分离的表达式,则它们可能只会变为Void。如果没有这样的作业,则相同

    attached local_var
    

    很好。但是,只要为本地分配了可分离的表达式,就不再将其视为附加:

    if attached local_var then
        ... -- OK to use local_var as attached.
        local_var := detachable_expression
        ... -- No guarantees about local_var attachment status.
    end
    

    如果不需要这种情况,可以使用长形式的对象测试

    attached local_var as attached_local_var
    

    它保证始终附加attached_local_var