可变的基类: Vector3
public class Vector3 {
public static final Vector3 Zero = new ImmutableVector3(0, 0, 0);
private float x;
private float y;
private float z;
public Vector3(float x, float y, float z) {
this.x = x;
this.y = y;
this.z = z;
}
public void set(float x, float y, float z) {
this.x = x;
this.y = y;
this.z = z;
}
}
不可变版本:ImmutableVector3
(注:该内容涉及IT技术)public final class ImmutableVector3 extends Vector3 {
public ImmutableVector3(float x, float y, float z) {
super(x, y, z);
}
//Made immutable by overriding any set functionality.
@Override
public void set(float x, float y, float z) {
throw new Exception("Immutable object."); //Should I even throw an exception?
}
}
我的使用情境如下:
public class MyObject {
//position is set to a flyweight instance of a zero filled vector.
//Since this is shared and static, I don't want it mutable.
private Vector3 position = Vector3.Zero;
}
假设我的团队中的一位开发者决定需要操纵对象的位置,但目前它被设置为静态、不可变的Vector3.Zero共享向量实例。
如果他事先知道需要创建一个新的可变向量实例,那么将位置向量设置为Vector3.Zero的共享实例会更好:
if (position == Vector3.Zero)
position = new Vector3(x, y, z);
但是,假设他没有先检查这个。我认为,在这种情况下,在ImmutableVector3.set(x,y,z)
方法中像上面那样抛出一个异常会很好。我想使用标准的Java异常,但我不确定哪个最合适,而且我也不完全相信这是处理这个问题的最佳方式。
我在(这个问题)[Is IllegalStateException appropriate for an immutable object?中看到的建议似乎如下:
- IllegalStateException - 但它是一个不可变对象,因此只有一个状态
- UnsupportedOperationException -
set()
方法不受支持,因为它覆盖了基类,所以这可能是一个不错的选择。 - NoSuchElementException - 我不确定除非该方法被认为是一个
element
,否则这将是一个好选择。
此外,我甚至不确定我是否应该在这里抛出异常。我可以简单地不更改对象,并且不警告开发人员他们正在尝试更改一个不可变对象,但这似乎也很麻烦。在ImmutableVector3.set(x,y,z)
中抛出异常的问题在于,set
必须在ImmutableVector3
和Vector3
上都抛出异常。因此,即使Vector3.set(x,y,z)
永远不会抛出异常,它也必须放置在一个try/catch
块中。
- 除了抛出异常,我是否忽略了其他选项?
- 如果异常是最好的选择,我应该选择哪个异常?
UnsuppoertedOperationException
。来自Collection
的unmodifiable*
修饰符是一个很好的先例。 - kiheru