简体   繁体   中英

Eiffel: best way to create a redefinable “constant”

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

That's not doable

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

Alternative with once instance_free

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

Alternative with attribute

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

  • constants are frozen and, therefore, cannot be redefined;
  • instance-free attributes are not supported.

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:

  1. 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.

  2. 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.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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