I wish to alert the developer when he attempts to mutate an immutable object. The immutable object is actually an extension of a mutable object, and overrides the setters on said object to make it immutable.
Mutable base class: 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;
}
}
Immutable version: ImmutableVector3
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?
}
}
My use case is as follows:
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;
}
Let's say that a developer on my team decides he needs to manipulate the position of the object, but currently it's set to the static, immutable Vector3.Zero shared vector instance.
It would be best if he knew ahead of time that he needs to create a new instance of a mutable vector if the position vector is set to the shared instance of Vector3.Zero:
if (position == Vector3.Zero)
position = new Vector3(x, y, z);
But, let's say he doesn't check this first. I think, in this case, it would be good to throw an Exception as shown above in the ImmutableVector3.set(x,y,z)
method. I wanted to use a standard Java exception, but I wasn't sure which would be most fitting, and I'm not 100% convinced this is the best way to handle this.
The suggestions I've seen on (this question)[Is IllegalStateException appropriate for an immutable object? seem to suggest the following:
- IllegalStateException - but it's an immutable object, thus only has a single state
- UnsupportedOperationException - the
set()
method is unsupported since it overrides the base class, so this might be a good choice. - NoSuchElementException - I'm not sure how this would be a good choice unless the method is considered an
element
.
Furthermore, I'm not even sure I should throw an exception here. I could simply not change the object, and not alert the developer that they are trying to change an immutable object, but that seems troublesome as well. The problem with throwing an exception in ImmutableVector3.set(x,y,z)
is that set
has to throw an Exception on both ImmutableVector3
and Vector3
. So now, even though Vector3.set(x,y,z)
will never throw an exception, it has to be placed in a try/catch
block.
- Am I overlooking another option besides throwing exceptions?
- If exceptions are the best way to go, which exception should I choose?