supsupsupsup
supsupsupsup

Reputation: 11

Java - Edit instance variables without a method

I am quite new to Java, and I am constantly looking for ways to improve my code. But I don't seem to get this, if it is even possible to do.

Let's say I have this code (I edited out the irrelevant parts, so the code might seem weird):

public class NewBody {

public static int distanceScale = 5;

    public int x, y;
    public float xMeter = x * distanceScale;
    public float yMeter = y * distanceScale;

    public NewBody(int x, int y){
        this.x = x;
        this.y = y;
    }

    public void pixToMeter(){
         this.xMeter = distanceScale * this.x;
    }

If I don't call pixToMeter() and just try to use "instance.xMeter" directly, it just returns the vaulue 0, even though I've already set the x variable in the constructor.

So my question is: Is there a way to properly set variables without calling a method to do it? It seems highly unneccessary since I am not even passing a parameter to it.

Sorry for my poor english, I hope you understand what I am trying to say.

Upvotes: 1

Views: 382

Answers (3)

Joop Eggen
Joop Eggen

Reputation: 109547

The initialisation of xMeter is done when x is still zero.

This is what actually happens:

public NewBody(int x, int y) {
    // All fields are zeroed: 0, null, 0.0.

    super(); // Object constructor, as Object is the parent class.

    // Those fields that are initialized:
    xMeter = this.x * distanceScale; // 0.0f * 5
    yMeter = this.y * distanceScale;

    // The rest of the constructor:
    this.x = x;
    this.y = y;
}

For a depending value:

public final void setX(int x) {
    this.x = x;
    xMeter = this.x * distanceScale;
}

And to apply the DRY principle (Don't Repeat Yourself): one could drop the initialisation of xMeter and call setX(x) in the constructor instead.

When called in the constructor it is important to make setX final, that is: not overridable.

Upvotes: 4

Michael Yaworski
Michael Yaworski

Reputation: 13483

As others have mentioned, when the xMeter is initialized, the constructor is not called yet and x is still 0, so the value of xMeter is 0 as well.

To change that, you must update xMeter's value once x is initialized in the constructor, like so:

public NewBody(int x, int y){
    this.x = x;
    this.y = y;

    // update x and y meter
    xMeter = x * distanceScale;
    yMeter = y * distanceScale;
}

However, you mentioned how you want xMeter to update every time x is changed as well. As it stands with your current code, that will not happen. However, a suggestion of mine would be to create a method to change the value of x (and y as well) and in those methods, also update the values of xMeter and yMeter. That way, whenever you want to change x, call the methods and it will update your other values too.

Try adding these methods and changing your constructor to this:

// called setter methods
public void setX(int x) {
    this.x = x;
    this.xMeter = x * distanceScale;
}
public void setY(int y) {
    this.y = y;
    this.yMeter = y * distanceScale;
}

// constructor
public NewBody(int x, int y){
    setX(x);
    setY(y);
}

Upvotes: 1

Paul Richter
Paul Richter

Reputation: 11072

The source of the problem is here:

public float xMeter = x * distanceScale;

The issue is that you're initializing this instance variable outside the constructor. As a result, since x is initialized to 0, the result of your multiplication is also 0.

If you need xMeter and yMeter initialized to a value based on x or y, simply declare them as you did the other fields:

public int xMeter;

And initialize their values in the constructor:

public newBody(int x, int y){
    // initialize x and y ...
    this.xMeter = x * distanceScale;

Upvotes: 2

Related Questions