[英]What's the point of the local variable in Eiffel's attached-statement?
在Eiffel中,Void Safety是一种静态防止取消引用未初始化(“null”)对象的方法。 它的工作方式是,首先,必须将对象声明为可拆卸 ,然后您需要在使用它之前检入if-block是否实际附加了对象(即具有某些值)。
这是我到目前为止使用它的方式:
some_object: detachable TYPE
...
if attached some_object then
some_object.method
end
工作完全正常:没有附加检查,编译失败,“Object_call的目标可能无效”错误。 但是,在实际阅读有关Void Safety的文档之后,我了解到这实际上是这样的:
some_object: detachable TYPE
...
if attached some_object as l_some_object then
l_some_object.method
end
在这种形式中, l_some_object
是if块的本地变量,它指向与some_object
相同的对象,但静态保证是非void。
但是,我没有看到这个as-clause存在的原因。 正如我在上面指出的那样,显然原来的some_object
已经在if-block中静态保证是非空的,那么引入另一个变量又有什么意义呢?
除范围外, some_object
和l_some_object
之间有什么区别?
简短的回答
如果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
使得代码void-unsafe:
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
(这可以间接完成),则代码再次为void-unsafe。
最后,在多线程环境中,另一个线程可能会在检查之后以及在“then”部分内部使用之前更改attr
的值,即使没有任何中间功能调用:
if attached attr then -- Attribute attr is attached here.
-- Another thread sets attr to Void.
attr.do_something -- BOOM!
end
为了防止这些情况,使用var
部分。 此对象测试local是只读的,不受任何中间功能调用或其他线程对同一表达式的评估的影响。 换句话说,它始终是附加的。
在某些情况下,对象测试表达式不受这些因素的影响:
参数是只读的,因此使用简短形式总是足够的
attached arg
引入对象测试局部是没有意义的,因为它总是等于参数。
如果为局部变量和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
始终附加。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.