The Teluri
The Teluri

Reputation: 23

Can i make a class that behave like a primitive type?

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

Answers (2)

KeukenkastjeXYZ
KeukenkastjeXYZ

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

Marco13
Marco13

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

Related Questions