As mentioned on this question, there is no way to define a constant which I can redefine into a descendant.
In many of my cases, I'd like to have a constant which I can redefine. The alternatives I see to avoid a creation on each consultation which doesn't make sense would be
class A
feature -- Access
Default_value: STRING = "some A value"
end -- Class
class B
inherit
B
redefine
Default_value
end
feature -- Access
Default_value: STRING = "some B value"
end -- Class
class A
feature -- Access
Default_value: STRING
once
Result := "some A value"
ensure
instance_free: class
end
end -- Class
class B
inherit
B
redefine
Default_value
end
feature -- Access
Default_value: STRING
once
Result := "some B value"
ensure
instance_free: class
end
end -- Class
As far as I understand, the once wouldn't be created with B value as the A class value would be taken
class A
feature -- Access
Default_value: STRING
attribute
Result := "some A value"
ensure
instance_free: class
end
end -- Class
class B
inherit
B
redefine
Default_value
end
feature -- Access
Default_value: STRING
attribute
Result := "some B value"
ensure
instance_free: class
end
end -- Class
Would it be the only and good practice to do it?
Out of 3 mentioned possibilities, only instance-free once functions can be used because
One more way is to use regular functions with manifest once strings to guarantee that result is always the same:
class A feature
default_value: STRING
do
Result := once "some A value" -- Note the modifier "once".
ensure
instance_free: class
constant: Result = default_value -- Ensure the Result is constant.
end
end
However, there seems to be no particular benefit compared to instance-free once functions. (I would still keep the postcondition constant
to avoid erroneous redeclaration of the feature.)
Edit. Some details for the example above:
At run-time, regular manifest strings of the form "foo"
create a new string object every time they are evaluated. Once manifest strings of the form once "foo"
create a new string object only for the first time instead. On subsequent evaluation, they produce the same object that was computed earlier.
Postcondition Result = f
of a query f
(the example uses default_value
instead of f
) ensures that the second call to f
produces the same object as the first call. Indeed, in expression Result = f
, Result
refers to the object computed by the feature. The call f
refers to the object computed by the second call to the feature. So, whenever we call f
, it produces the same object. (Ideally, we would explicitly require that the third, fourth, etc. calls to the feature also produce the same object. However, this is beyond expressive power of the language. Formally, the equality of all results produced by f
could be proved by induction.)