how to make a variable unchangeable so it can’t be changed anymore?
i tried this but it doesn’t work, does it not work on pvectors or is it because it was in the middle of my code instead of at the top?
Not sure though it might not make sense to allow final with pvectors considering all the functionality pvectors have.
Please note that
This keyword is an essential part of Java programming and is not usually used with Processing. Consult a Java language reference or tutorial for more information.
final
works great with primitive variables like int
float
and boolean
. If you save a final float x
and final float y
, that is all you need.
PVector is an object with internal variables x, y, z. You can create a final PVector variable and only one object can be assigned to it – you can’t assign a new object to that variable – but that doesn’t mean the object itself cannot be changed internally.
The PVector is final, but its x, y, z are not final.
final PVector foo = new PVector(10,10);
foo = new PVector(20,20);
Once you use final
the second line is illegal and show the error message:
The final local variable foo cannot be assigned.
However, being final doesn’t make it immutable.
final PVector foo = new PVector(10,10);
foo.rotate(PI);
println(foo);
[ -9.999999, -10.000001, 0.0 ]
foo.x = 123;
[ 123.0, -10.000001, 0.0 ]
If you have PVectors and you don’t want your code to accidentally change them, there are several ways to approach it:
- The easiest thing – don’t call mutator methods on your PVectors.
- Create a class like a PVector,
class MyVector
, with final x, y, z and only the methods that you want – add, or rotate. - Extend PVector and make a class that with a final x, y, z. This gets a bit tricky with how you handle overriding, but it can be demonstrated – it just usually isn’t worth it. In particular, in addition to overriding methods like add, rotate, etc., you’ll want to override toString so that the class doesn’t print 0,0,0, the values of its shadowed variables.
- Don’t: Extend PVector and make a class that overrides every mutator method in order to disable them. This doesn’t really work well with PVector because if x and y are directly exposed, so you can always pv.x = 123. To be safe, use method 3 instead.
- Wrap a PVector inside a new class, e.g. VecWrapper, which has a private PVector variable and only lets you create it or read it but not change it.
You may also be interested in the idea of unmodifiable – an interface that doesn’t provide ways of changing a thing – vs immutable – a guarantee that nothing can change a thing.
The solutions above are either to make your own immutable thing, or to extend it or wrap a PVector in ways that make it unmodifiable (even though, inside, it can still be changed).
Java objects aren’t really great at being deeply immutable unless they were first created that way by design to have things made of things made of things none of which can change. So often, even if you make a static or final collection of stuff, there may be changeable stuff inside it. The list can’t change, but the parts can.