Reputation: 23
I made a Point class to manage xy coordinate (I know some java default packages already have some Point object that behave in a similar way, I use it as a lazy alternative and this is an example, please dont mind it ^^).
Before using it I was using the int primitive type.
thing is, when passing a class or a primitive type as parameter of a method, both don't act the same way, if I change the value of a primitive variable in a method, the original variable is unaffected, unlike if I was using an object since its the reference that is passed as parameter.
my problem is that since I use Point for math (example below), I have to manually create new object to save the result and I never use it to have a "link" between two variables as I could with how object behave usually.
My Point class:
public class Point {
public int x;
public int y;
public Point(int nx, int ny) {
this.x = nx;
this.y = ny;
}
public Point() {
this(0, 0);
}
}
An example of method:
public Point getAdjacent(int x, int y, Direction dir) {
Point pt = new Point(x, y);//basically, i would like to do that automatically
switch (dir) {
case Up:
pt.y -= 1;
break;
case Down:
pt.y += 1;
break;
case Right:
pt.x -= 1;
break;
case Left:
pt.x += 1;
break;
default:
//do nothing
}
return pt;
}
To summarize, is it possible to make Point behave like a primitive type?
EDIT: i mean that it would automatically copy it when passing it as parameter or doing point1=point2
Upvotes: 1
Views: 588
Reputation: 219
First of all: be sure to use break statements in your switch code. Otherwise when case Up is matched, the switch block will "fall through" and will execute:
pt.y -= 1;
pt.y += 1;
pt.x -= 1;
pt.x += 1;
(Reference: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/switch.html)
According to the question, you can indeed use the Point class. Below code will:
1. Use a Point as input.
2. Extract the variables x and y from the input Point into a copy primitive.
3. Change the copied primitives.
4. Create a new Point, based on the copies.
In this way the "old" Point will be left untouched.
public Point getAdjacent(final Point point, final Direction dir) {
int x = point.x;
int y = point.y;
switch (dir) {
case Up:
y -= 1;
break;
case Down:
y += 1;
break;
case Right:
x -= 1;
break;
case Left:
x += 1;
break;
default:
break;
}
return new Point(x, y);
}
Upvotes: 1
Reputation: 54639
The question might be a bit too broad, because one could argue quite extensively about what the word "behave" should mean. But to some extent, we can sort this out:
The shortest answer might be: No, this is not possible.
A slightly more elaborate answer might be: No, it is not yet possible to let a class (or more precisely: an object) behave like a primitive value.
The long answer:
There are efforts to achieve a behavior that might come close to what you're trying to accomplish. The relevant keyword here is Value Types.
Some resources:
However, this is not supported in current versions of Java and the JVM, and it might still take a while until the details are sorted out.
Until then, there are some conceivable workarounds to achieve the desired goal.
The simplest solution is the one that you already proposed: You always return a new instance instead of modifying a given object.
The example that you showed in the question might not be the best to illustrate this, because the method getAdjacent
that you showed could in fact be a static
method. It does not use the instance that it is called on in any way.
Then you could always be sure that you received a new instance for each modification. Otherwise, imagine this code snippet:
Point a = new Point(1,2);
Point b = new Point(3,4);
a.add(b);
System.out.println(a); // What does this print?
Depending on the implementation of the add
method, the behavior might not be clear. If it was implemented like this:
public void add(Point other) {
this.x += other.x;
this.y += other.y;
}
then the point a
would be modified, and the output would be (4,6)
.
But if it was implemented like this
public Point add(Point other) {
return new Point(this.x+other.x, this.y+other.y);
}
then a
would remain unaffected, and the output would still be (1,2)
.
In general, making something like a Point
immutable basically enforces this style of programming. So you could make the variables x
and y
in your class final
, so that you could always be sure that the object cannot be modified after it was created:
public class Point {
// Note that these are FINAL:
private final int x;
private final int y;
public Point(int nx, int ny) {
this.x = nx;
this.y = ny;
}
...
}
There are some further design considerations for such a seemingly trivial thing like a Point
class (some of which I mentioned in this answer), but discussing them is beyond the scope of this answer.
Upvotes: 2