Home > Software engineering >  How can my class which extends an abstract class use its own variables?
How can my class which extends an abstract class use its own variables?

Time:03-26

I have two classes which uses several equal methods, so I thought I could use an abstract class instead of an interface to allow the abstract class to have method bodies, and reduce duplication of code in the other classes. But I get an error saying x is "null" when running my main function, and I believe that is because it uses the empty variable from the abstract class. But for my method in the abstract class I need to declare the variables the methods uses, so how do I get it to use the variables from my subclass? Specifically, the error is in AGameFigures setPosition() for bottom.x = x;

Here is my code:

abstract class AGameFigures {
public Rectangle hitbox;
int action;
ICollision collision;
float tileHeight, tileWidth;
float spriteHeight, spriteWidth;
float velocityY;

public AGameFigures(){
    this.hitbox = hitbox;
    this.action = action;
    this.collision = collision;
    this.tileHeight = tileHeight;
    this.tileWidth =tileWidth;
    this.spriteHeight = spriteHeight;
    this.spriteWidth = spriteWidth;
    this.velocityY = 0;
}

public void update(float delta) {
    float oldY = hitbox.y;
    hitbox.y  = velocityY;
    velocityY -= (25 * delta);

    boolean collisionDown = false;
    boolean collisionUpwards = false;

    if(velocityY < 0) {
        collisionDown = collision.collidesDownwards(hitbox.x, hitbox.y);
    } else if(velocityY > 0) {
        collisionUpwards = collision.collidesUpwards(hitbox.x, hitbox.y);
    }
    if(collisionDown) {
        hitbox.y = (int) (oldY / tileHeight) * tileHeight;
        velocityY = 0;
    }
    if(collisionUpwards) {
        hitbox.y = (int) ((hitbox.y spriteHeight/2) / tileHeight) * tileHeight;
        if(velocityY > 0)
            velocityY = 0;
        velocityY -= (25 * delta);
    }
}
public void setPosition(float x, float y) {
    hitbox.x = x;
    hitbox.y = y;
}

abstract void moveLeft(float delta);

abstract void moveRight(float delta);

public void setVelocityY(float newVelY) {
    velocityY = newVelY;
}
public void jump() {
    if (velocityY == 0)
        velocityY = 7;

}
public int hits(Rectangle r) {
    if(hitbox.overlaps(r))
        return 1;
    return -1;
}

}

public class GamePlayer extends AGameFigures{

public Rectangle hitbox;
int action;
float tileHeight, tileWidth;
float spriteHeight, spriteWidth;
ICollision collision;
float velocityY;


public GamePlayer(float spriteHeight, float spriteWidth, ICollision collision) {
    hitbox = new Rectangle(0.0f, 0.0f, 128.0f, 128.0f);
    velocityY = 0;
    hitbox.x = 0; hitbox.y = 0;
    tileWidth = collision.getTileWidth(); tileHeight = collision.getTileHeight();
    this.spriteHeight = spriteHeight; this.spriteWidth = spriteWidth;
    this.collision = collision;
}

public void action(int type, float x, float y) {
    if(type == 1) {
        velocityY = 0;
        setPosition(hitbox.x, y);
    }
}

@Override
public void moveLeft(float delta) {
    hitbox.x -= (200 * delta);  // delta == "change of time" "for fluid change om motion"
    if(collision.collidesLeftwards(hitbox.x, hitbox.y)) {
        hitbox.x = (int) (hitbox.x / tileWidth) * tileWidth   spriteWidth;
    }
}
@Override
public void moveRight(float delta) {
    hitbox.x  = (200 * delta);  // (value) * delta, endre value for å endre movementspeed
    if(collision.collidesRightwards(hitbox.x, hitbox.y)) {
        hitbox.x = (int) (hitbox.x / tileWidth) * tileWidth;
    }
}

}

CodePudding user response:

From the AGameFigures constructor:

public AGameFigures(){
    this.hitbox = hitbox;
    ... 
}

There are no arguments passed to the constructor, so hitbox refers to the class instance field, which is null. This line of code from the constructor:

this.hitbox = hitbox;

is effectively:

this.hitbox = null;

So later on a null ponter is encountered. The constructor needs to be updated to pass the arguments:

public AGameFigures(Rectangle hitbox, ...){
    this.hitbox = hitbox;
    ... 
}

and the sub-classes will need to provide the constructor argument values.

GamePlayer defines its own hitbox which is probably causing some confusion. hitbox should be removed from GamePlayer, and just rely on the base class.

Check the compiler warnings, and do not (usually) ignore them!

CodePudding user response:

why you diclare the sames filed in superclass and subclass

CodePudding user response:

I think that your issue is in the constructor of the abstract class. The variables will always be null.

You need to provide params in the constructor:

public AGameFigures(Hitbox hitbox, int action, ICollision collision, float tileHeight, float tileWidth, float spriteHeight, float spriteWith, float velocityY){
    this.hitbox = hitbox;
    this.action = action;
    this.collision = collision;
    this.tileHeight = tileHeight;
    this.tileWidth =tileWidth;
    this.spriteHeight = spriteHeight;
    this.spriteWidth = spriteWidth;
    this.velocityY = 0;
}

And, you don't need to repeat the variables which are inherited.

  • Related