In Eiffel, Void Safety is a way to statically prevent dereferencing uninitialised ("null") objects. 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 (i.e. has some value) before you can use it.
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. However, after actually reading the documentation on Void Safety, I learned that this is actually how it's supposed to look like:
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.
However, I don't see the reason for the existence of this 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?
What are the differences between some_object and l_some_object, apart from the scope?
Short answer
If
some_objectis a local variable, there is no point to introduce an object test locall_some_object.Long answer
The general form of an object test is
where
{SOME_TYPE}andvarare optional. When type ({SOME_TYPE}in the example above) is not used, the object test just checks whetherexpris attached or not and assigns its value tovarwhen it is attached.In theory something like the following could be expected to be void-safe:
However this is not allowed in general case because
exprmight have side effects, so that the second time it is computed, a different value is returned, and this value might bevoidmaking the code void-unsafe:Another possibility is an intermediate call that changes value of the expression, for example,
If
barsets attributeattrtovoid(this can be done indirectly), the code is void-unsafe again.Finally in a multithreading environment another thread may change the value of
attrafter the check and before its use inside "then" part even without any intermediate feature call:To prevent these situations, the
varpart is used. 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. In other words it is always attached.Still in some situations an object tests expression is not affected by these factors:
Arguments are read-only, so it is always sufficient to use the short form
and it makes no sense to introduce an object test local because it will always be equal to the argument.
Local variables and
Resultmay only becomeVoidif they are assigned a detachable expression. If there is no such an assignment, the sameis just fine. However as soon as the local is assigned a detachable expression, it is not considered attached anymore:
If this scenario is not desired, the long form of the object test can be used
and it guarantees that
attached_local_varis always attached.