Search code examples
javaoopinheritancesubclasssuperclass

Inherit subclass variable by super in Java


This title does not express what I mean quite well, I apologize, but it is difficult for me to express it better, because I don't quite understand what's going on due to lack of OOP knowledge and experience.

I am building a basic game, which is going to have the player run around a board with a 'hero' sprite, being chased by a 'badGuy' sprite. Because the two sprites share 5-6 methods, I decided to make a super class 'Sprite' and two classes 'Hero extends Sprite' and 'BadGuy extends Sprite'. Now for all those super methods, including stuff like:

getX(); getY(); getBounds(); render();

to work I need the super class to track the location of 'Hero' and 'badGuy'. So I implemented 'Sprite' like this:

package game.sprites;

import javafx.scene.shape.Rectangle;

import javax.swing.*;
import java.awt.*;

public class Sprite {

    public static int x;
    public static int y;
    private int imageWidth;
    private int imageHeight;
    public Image image;

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

    public static void render(Graphics g, Image image) {
        g.drawImage(image, x, y, null);
    }

    public Image loadImage(String filePath) {...}

    public void getImageDimensions() {...}

    public Rectangle getBounds() {
        return new Rectangle(x, y, imageWidth, imageHeight);
    }

    public Image getImage() {
        return image;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }
}

The problem kicks in when I want to give different starting coordinates to 'Hero' and 'BadGuy' objects. Currently if I set them different, the second call of 'Sprite' overrides the first and both start at the same spot (which would be very frustrating if your goal is to run from 'badGuy'). 'Hero' and 'BadGuy' are currently initialized this way:

public class BadGuy extends Sprite {

    public BadGuy() {
        super(x, y);
        initBadGuy();
    }

    public void initBadGuy() {
        loadImage("resources/craft.gif");
        getImageDimensions();
        x = 860; // Hero x = 20;
        y = 560; // Hero y = 20;
    }

So what I tried to do is make the subclasses override Sprite's x and y. But I googled it and I understand that this is very bad idea and thus it is not possible. So my question is something like: How can I make 'Sprite' inherit subclass 'x' and 'y' variables and perform the necessary methods when the certain subclass is called.

Now that I look at it - both the constructor and init<>() are identical for the subclasses, so maybe they can be implemented in 'Sprite' instead? Just a thought, but I'm getting quite confused already, so no idea.

Thanks.


Solution

  • You are getting this problem because x and y are declared as static fields in your Sprite class.
    From JLS 8.3.1.1. static Fields

    If a field is declared static, there exists exactly one incarnation of the field, no matter how many instances (possibly zero) of the class may eventually be created. A static field, sometimes called a class variable, is incarnated when the class is initialized (§12.4).

    Use following code:

    Change your Sprite Class like below:

    public class Sprite {
    
        public int x;
        public int y;
        ....
    }
    

    BadGuy class:

    public class BadGuy extends Sprite {
        public BadGuy(int x, int y) {
           super(x, y);
            ...
        }
      ....
    }
    

    Hero class:

    public class Hero extends Sprite {
        public Hero(int x, int y) {
           super(x, y);
            ...
        }
      ....
    }
    

    From Main class do following: //From where you want to create Object of both classes

    public static void main(String[] args){
     Hero hero = new Hero(20,20);
     BadGuy badGuy= new BadGuy(860,560);
    }