为什么Groovy中的不可变类是可变的?

时间:2017-06-09 04:17:00

标签: groovy immutability

阅读Benjamin J. Evans和Martijn Verburg撰写的“The Well-Grounded Java Developer”一书我在Groovy中遇到了以下示例:

class Character {
    private int strength
    private int wisdom
}

def pc = new Character(strength: 10, wisdom: 15)
pc.strength = 18
println "STR [" + pc.strength + "] WIS [" + pc.wisdom + "]"

摘录的输出如下:

STR [18] WIS [15]

直到现在还没有问题。正如本书建议的那样,上面的代码已经使用@Immutable注释稍作修改:

import groovy.transform.*

@Immutable
class Character {
    private int strength
    private int wisdom
}

def pc = new Character(strength: 10, wisdom: 15)

pc.strength = 18

println "STR [" + pc.strength + "] WIS [" + pc.wisdom + "]"

最后一个片段的输出仍然相同:

STR [18] WIS [15]

预期的结果是什么,但不像上面的那个...

为什么不可变类的对象看起来像一个可变的对象呢? Groovy中的不变性概念是否允许修改类字段?

2 个答案:

答案 0 :(得分:4)

为了解决您报告的问题很简单,即删除access modifier to fields。这应该可以解决问题。

import groovy.transform.Immutable
@Immutable
class Character {
    int strength
    int wisdom
}

def pc = new Character(strength: 10, wisdom: 15)

pc.strength = 18

println "STR [" + pc.strength + "] WIS [" + pc.wisdom + "]"

现在,它会引发异常,如下所示:

  

groovy.lang.ReadOnlyPropertyException:无法设置readonly属性:类的强度:字符
      在Character.setProperty(Script1.groovy)
      在Script1.run(Script1.groovy:10)

如果您想了解行为不同的详细信息,请参阅here

答案 1 :(得分:2)

将字段显式设置为private时,会出现此行为。 Immutable州的文档:

  

您不必遵循Groovy的正常财产惯例,例如您可以创建一个显式的私有字段,然后您可以编写显式的get和set方法。这种方法目前还没有被禁止(给你一些摆动这些约定的余地)但是以这种方式创建的任何字段都被认为不属于对象的重要状态并且没有考虑到equals或hashCode方法。