Искам да предупредя разработчика, когато се опитва да промени неизменен обект. Неизменният обект всъщност е разширение на променлив обект и отменя сетерите на споменатия обект, за да го направи неизменен.
Променлив базов клас: 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
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 изключение, но не бях сигурен кое би било най-подходящо и не съм 100% убеден, че това е най-добрият начин да се справя с това.
Предложенията, които видях на (този въпрос) [IllegalStateException подходящо ли е за неизменен обект? изглежда предполагат следното:
- IllegalStateException - но това е неизменен обект, следователно има само едно състояние
- UnsupportedOperationException - методът
set()
не се поддържа, тъй като замества базовия клас, така че това може да е добър избор. - NoSuchElementException - Не съм сигурен как това би било добър избор, освен ако методът не се счита за
element
.
Освен това дори не съм сигурен, че трябва да направя изключение тук. Мога просто да не променя обекта и да не предупредя разработчика, че се опитват да променят неизменен обект, но това също изглежда обезпокоително. Проблемът с хвърлянето на изключение в ImmutableVector3.set(x,y,z)
е, че set
трябва да хвърля изключение както на ImmutableVector3
, така и на Vector3
. Така че сега, въпреки че Vector3.set(x,y,z)
никога няма да хвърли изключение, той трябва да бъде поставен в try/catch
блок.
- Пренебрегвам ли друга опция освен хвърлянето на изключения?
- Ако изключенията са най-добрият начин, кое изключение да избера?
UnsuppoertedOperationException
.unmodifiable*
декораторите отCollection
са добър прецедент. - person kiheru   schedule 29.08.2013