埃菲尔不可变的阶级

Fer*_*jka 5 eiffel point invariants immutability

我想POINT在埃菲尔做一个不可变的课.下面的代码定义了一个吗?和字段的{NONE}可访问性是否足够?我可以写一些类不变的类,或者我怎样才能实现不变性?xyx = x'

class POINT
    create
        make
    feature {NONE}
        x: DOUBLE
        y: DOUBLE
    feature
        make (x_: DOUBLE; y_: DOUBLE)
        do
            x := x_
            y := y_
        ensure
            set: x = x_ and y = y_
        end

    feature --accessors
        get_x: DOUBLE
        do
            Result := x
        ensure
            Result = x
        end
    end
Run Code Online (Sandbox Code Playgroud)

Ale*_*kov 5

Eiffel不允许其客户端更改类的属性.例如,以下代码被拒绝:

p: POINT
...
p.x := 5.0
Run Code Online (Sandbox Code Playgroud)

因此,不需要提供getter(就像其他语言一样).你可以只使用p.x提供了x充分导出到客户端类.因此,您的示例代码可以简化为

class POINT
create
   make
feature -- Access
   x: DOUBLE
   y: DOUBLE
feature {NONE} -- Creation
   make (x0: DOUBLE; y0: DOUBLE)
      -- Initialize object with `x0' and `y0'.
   do
      x := x0
      y := y0
   ensure
      set: x = x0 and y = y0
   end
end
Run Code Online (Sandbox Code Playgroud)

请注意,不再导出创建过程,否则可以将其用作普通(即非创建)例程并更改属性,即我们可以执行以下操作

create p.make (1, 1)
p.make (2, 3)
print (p)
Run Code Online (Sandbox Code Playgroud)

这将打印(2, 3),即您将能够更改原始对象的值p,使其可变.

虽然现在不能直接更改属性,但仍然可以copy在类型对象上调用feature POINT并更改整个对象.如果您也想避免这种情况,可以在类中重新定义该功能POINT以引发异常,甚至可以使后置条件False导致运行时为您引发异常:

copy (other: like Current)
      -- <Precursor>
   do
      (create {EXCEPTIONS}).raise ("Attempt to change an immutable object.")
   ensure then
      is_allowed: False
   end
Run Code Online (Sandbox Code Playgroud)