我的对象中只有一半是不可变的 - 我可以这样标记吗?

时间:2014-02-03 13:31:17

标签: groovy

我有一个groovy类 - 它的一半属性总是不可变的(并在构造期间设置),另一半是可变的。

有什么办法可以在Groovy中标记它吗?

1 个答案:

答案 0 :(得分:5)

在可变性或不变性方面,没有灰色阴影。

它有点像食物:"我有一个不可食用和半食用的汉堡......"

一种选择是将不可变部分提取到Immutable类,然后委托给你的可变部分,即:

import groovy.transform.*

@Immutable
class Point {
    int x, y
}

@Canonical
class Pixel {
    int color
    @Delegate Point point
}

Pixel p = new Pixel( 0xFF0000, new Point( 10, 10 ) )
assert p == new Pixel( 0xFF0000, new Point( 10, 10 ) )

// Change the mutable color
p.color = 0x00FF00
assert p == new Pixel( 0x00FF00, new Point( 10, 10 ) )

// Change the point (can be done as Pixel is mutable)
p.point = new Point( 10, 20 )
assert p == new Pixel( 0x00FF00, new Point( 10, 20 ) )

// Cannot change the Point properties
try {
    p.point.x = 20
    assert false
}
catch( e ) {
    assert e.class == ReadOnlyPropertyException
}

或者,如果可以使整个事物成为不可变的,您可以使用copyWith方法生成新的像素:

import groovy.transform.*

@Immutable
class Point {
    int x, y
}

@Immutable( copyWith=true )
class Pixel {
    int color
    @Delegate Point point
}

Pixel p = new Pixel( 0xFF0000, new Point( 10, 10 ) )
assert p == new Pixel( 0xFF0000, new Point( 10, 10 ) )

// Make a new copy with a new color
p = p.copyWith( color:0x00FF00 )
assert p == new Pixel( 0x00FF00, new Point( 10, 10 ) )

// Make a new copy with a new point
p = p.copyWith( point:new Point( 10, 20 ) )
assert p == new Pixel( 0x00FF00, new Point( 10, 20 ) )

// Cannot change the Point properties directly
try { p.point.x = 20 ; assert false }
catch( e ) { assert e.class == ReadOnlyPropertyException }

// or
try { p.color = 0x0000FF ; assert false }
catch( e ) { assert e.class == ReadOnlyPropertyException }