immutability - Eiffel 中的不可变类

标签 immutability point invariants eiffel

我正在尝试制作一个不可变的 POINT在 Eiffel 上课。下面的代码定义了一个吗? {NONE} x 的可访问性和 y字段就够了吗?我可以为类不变量写一些东西,比如 x = 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

最佳答案

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

p: POINT
...
p.x := 5.0

因此,不需要提供 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

注意创建过程是不是 不再导出,否则可以将其用作正常(即非创建)例程并更改属性,即我们可以执行以下操作
create p.make (1, 1)
p.make (2, 3)
print (p)

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

虽然现在不能直接更改属性,但仍然可以调用功能copyPOINT 类型的对象上并更改整个对象。如果您也想避免这种情况,可以在类 POINT 中重新定义该功能。引发异常,甚至有后置条件 False导致运行时为您引发异常:
copy (other: like Current)
      -- <Precursor>
   do
      (create {EXCEPTIONS}).raise ("Attempt to change an immutable object.")
   ensure then
      is_allowed: False
   end

关于immutability - Eiffel 中的不可变类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20938164/

相关文章:

ruby - 为什么你会 `replace` 而不是将新对象分配给同一个变量?

java - JDBC:如何读取MySQL点格式

Java/包含/等点类

c# - 不同泛型的数组

scala - 如何在 scala 中获取(不可变和可变)集合的列表?

java - 关于不可变类

reactjs - React,是否绝对有必要将 React 状态视为不可变?

d - float 的这个特性是什么?

mysql - 如何在 MySQL 数据库中维护递归不变量?

domain-driven-design - 类不变量如何加强前置条件和后置条件?