简体   繁体   English

埃菲尔附加声明中的局部变量有什么意义?

[英]What's the point of the local variable in Eiffel's attached-statement?

In Eiffel, Void Safety is a way to statically prevent dereferencing uninitialised ("null") objects. 在Eiffel中,Void Safety是一种静态防止取消引用未初始化(“null”)对象的方法。 The way it works is that first, the object has to be declared as detachable , and then you need to check in an if-block whether the object is actually attached (ie has some value) before you can use it. 它的工作方式是,首先,必须将对象声明为可拆卸 ,然后您需要在使用它之前检入if-block是否实际附加了对象(即具有某些值)。

This is how I have been using it until now: 这是我到目前为止使用它的方式:

some_object: detachable TYPE

...

if attached some_object then
  some_object.method
end

Works perfectly fine: Without the attached-check, compiling fails with an "Target of the Object_call might be void" error. 工作完全正常:没有附加检查,编译失败,“Object_call的目标可能无效”错误。 However, after actually reading the documentation on Void Safety, I learned that this is actually how it's supposed to look like: 但是,在实际阅读有关Void Safety的文档之后,我了解到这实际上是这样的:

some_object: detachable TYPE

...

if attached some_object as l_some_object then
  l_some_object.method
end

In this form, l_some_object is a variable local to the if-block which points to the same object as some_object but is statically guaranteed to be non-void. 在这种形式中, l_some_objectif块的本地变量它指向与some_object相同的对象,但静态保证是非void。

However, I don't see the reason for the existence of this as-clause. 但是,我没有看到这个as-clause存在的原因。 As I pointed out above, apparently the original some_object is already statically guaranteed to be non-void within the if-block, so what's the point of introducing another variable? 正如我在上面指出的那样,显然原来的some_object已经在if-block中静态保证是非空的,那么引入另一个变量又有什么意义呢?

What are the differences between some_object and l_some_object , apart from the scope? 除范围外, some_objectl_some_object之间有什么区别?

Short answer 简短的回答

If some_object is a local variable, there is no point to introduce an object test local l_some_object . 如果some_object是局部变量,则没有必要引入对象测试本地l_some_object

Long answer 答案很长

The general form of an object test is 对象测试的一般形式是

attached {SOME_TYPE} expr as var

where {SOME_TYPE} and var are optional. 其中{SOME_TYPE}var是可选的。 When type ( {SOME_TYPE} in the example above) is not used, the object test just checks whether expr is attached or not and assigns its value to var when it is attached. 如果未使用类型(上例中的{SOME_TYPE} ),则对象测试仅检查是否附加了expr并在附加时将其值赋给var

In theory something like the following could be expected to be void-safe: 从理论上讲,以下内容可能是无效的:

if attached expr then
    expr.do_something
end

However this is not allowed in general case because expr might have side effects, so that the second time it is computed, a different value is returned, and this value might be void making the code void-unsafe: 但是在一般情况下不允许这样做,因为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

Another possibility is an intermediate call that changes value of the expression, for example, 另一种可能性是改变表达式值的中间调用,例如,

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

If bar sets attribute attr to void (this can be done indirectly), the code is void-unsafe again. 如果bar将属性attr设置为void (这可以间接完成),则代码再次为void-unsafe。

Finally in a multithreading environment another thread may change the value of attr after the check and before its use inside "then" part even without any intermediate feature call: 最后,在多线程环境中,另一个线程可能会在检查之后以及在“then”部分内部使用之前更改attr的值,即使没有任何中间功能调用:

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

To prevent these situations, the var part is used. 为了防止这些情况,使用var部分。 This object test local is read-only and is not affected by an evaluation of the same expression, by any intermediate feature call or by another thread. 此对象测试local是只读的,不受任何中间功能调用或其他线程对同一表达式的评估的影响。 In other words it is always attached. 换句话说,它始终是附加的。

Still in some situations an object tests expression is not affected by these factors: 在某些情况下,对象测试表达式不受这些因素的影响:

  1. Arguments are read-only, so it is always sufficient to use the short form 参数是只读的,因此使用简短形式总是足够的

     attached arg 

    and it makes no sense to introduce an object test local because it will always be equal to the argument. 引入对象测试局部是没有意义的,因为它总是等于参数。

  2. Local variables and Result may only become Void if they are assigned a detachable expression. 如果为局部变量和Result分配了可分离的表达式,则它们可能只会变为Void If there is no such an assignment, the same 如果没有这样的任务,同样的

     attached local_var 

    is just fine. 很好。 However as soon as the local is assigned a detachable expression, it is not considered attached anymore: 但是,只要为本地分配了可分离的表达式,就不再将其视为附加:

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

    If this scenario is not desired, the long form of the object test can be used 如果不希望出现这种情况,可以使用长形式的对象测试

     attached local_var as attached_local_var 

    and it guarantees that attached_local_var is always attached. 它保证了attached_local_var始终附加。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM