What is the difference between twin
and deep_twin
which implies (and ensures) the difference between is_equal
and is_deep_equal
in eiffel?
twin
makes a copy of the current object. If the object references other objects, by default it does not make copies of these other objects. That's why it is said that the function makes a "shallow" copy. On the contrary, deep_twin
makes a copy not only of the current object, but also (recursively) copies of all other objects that are referenced by the current one. Here is an example
class A create make feature
make (value: STRING) do item := value end
item: STRING
end
a: A
...
a.item = a.twin.item -- Evaluates to True
a.item = a.deep_twin.item -- Evaluates to False
In the first comparison, the value of item
in the twin is the same string object as in the original object. In the second comparison, the value of item
in the twin is a new string object, equal to a.item
. In other words, if a.item = s
, then a.twin.item = s
, but a.twin.item = s1
where s1 /= s
, but s1 ~ s
.
is_equal
and is_deep_equal
are conterparts for the functions above. The first makes a "shallow" equality test, the second — a deep one. In the example, we have
a.is_equal (a.twin) -- Evaluates to True
a.is_deep_equal (a.twin) -- Evaluates to True
a.is_equal (a.deep_twin) -- Evaluates to False
a.is_deep_equal (a.deep_twin) -- Evaluates to True
If objects are "shallow" equal, they are also "deep" equal. But the reverse is not true.
All the above is valid with the assumption that the default versions of is_equal
and twin
are used. The features can be redefined to go deeper. For the class above we can add
is_equal (other: like Current): BOOLEAN
do
-- The default version is "Result := item = other.item"
Result := item ~ other.item -- Compare content rather than references
end
copy (other: like Current) -- twin is defined in terms of this procedure
do
-- The default version is "item := other.item"
item := other.item.twin -- Use a copy instead of the reference
end
With this redefinition, twin
/deep_twin
and is_equal
/is_deep_equal
become almost the same.