Home > OS >  How do I make a method that accepts all parameters that extend a certain class?
How do I make a method that accepts all parameters that extend a certain class?

Time:12-25

So if I have a class gameObject and a bunch of classes that extend it:

class gameObject {
int u = 0;
public gameObject() {
}
}
class Spaceship extends gameObject {
    int u = 5;
    // Constructor
    public Spaceship() {
    }

}
class Alien extends gameObject {
    int u = 6;
    public Alien() {
    }
}

public class test {
    public static int overlapping(gameObject b, gameObject a) {
        return (b.u - a.u);
    }
    public static void main(String[] args) {
        System.out.println(overlapping(new Alien(), new Spaceship())); 
    }
}

When the difference method runs, it computes 0 - 0 regardless of if a Spaceship, alien is passed into it. But I want it to take either of the 2 (Spaceship, Alien), and return the difference of their specific u values.

But indicating the type of a and b parameters as gameObject just results in the u value being taken as 0 instead of the specific values. What do I do here?

I thought that since all 2 extended gameObject, I could just say that the parameters were of gameObject type, but that didn't seem to work. I tried doing <T extends gameObject> and then Class <T> a and Class <T> b, but then it says that it cannot the constant u.

CodePudding user response:

With the code shared in the comments, the problem becomes clear.

Each of the class declares a new u member that hides the parents u member. Note the emphasis on hides - you can't "override members", so when you call .u on a reference to the base class, you'll still get the 0 it uses.

Instead of re-declaring the member, you should just overwrite its value. E.g.:

class Spaceship extends gameObject {
    public Spaceship {
        u = 5; // Reuse the base class' member
    }
}

CodePudding user response:

The (originally) posted code, after fixing some minor compilation errors and names, should work as expected:

public class Main {

    public static void main(String[] args) {
        System.out.println(difference(new Thing(), new Spaceship()));
    }

    public static int difference(GameObject a, GameObject b) {
        return a.getX() - b.getX();
    }
}

class GameObject {

    private final int POS_X = 0;
    // returns the current x coordinate of GameObject
    int getX() {
        return POS_X;
    }
}

class Spaceship extends GameObject {

    private final int POS_X = 1;

    @Override
    int getX() {
        return POS_X;
    }
}
class Alien extends GameObject {

    private final int POS_X = 2;

    @Override
    int getX() {
        return POS_X;
    }
}

class Thing extends GameObject {

    private final int POS_X = 3;

    @Override
    int getX() {
        return POS_X;
    }
}

I would recommend having all objects implement the same interface instead of extending the same base class:

interface  GameObject {
    // returns the current x coordinate of GameObject
    default int getX() {
        return 0;
    }
}

class Spaceship implements GameObject {

    private final int POS_X = 1;

    @Override
    public  int getX() {
        return POS_X;
    }
}

Alternatively, if the values are constant use an enum:

public class Main {

    public static void main(String[] args) {
        System.out.println(difference(GameObject.THING, GameObject.SPACESHIP));
    }

    public static int difference(GameObject a, GameObject b) {
        return a.getX() - b.getX();
    }
}

enum  GameObject {

    SPACESHIP(1), ALIEN(2), THING(3);
    private  int positionX;
    GameObject(int positionX){
        this.positionX = positionX;
    }

    int getX() {
        return positionX;
    }
}

CodePudding user response:

I'm not sure how are you using your method difference and I saw some errors in the code your provided (like you're missing a closing bracket after every class), but for example your code works for me if I include everything in one class like this:

public class TestStackOverflow {

static class gameObject {

    int POS_X = 0;

    // returns the current x coordinate of gameObject
    int getX() {
        return POS_X;
    }
}

static class Spaceship extends gameObject {

    int POS_X = 1;

    // returns the current x coordinate of gameObject
    int getX() {
        return POS_X;
    }
}

static class Alien extends gameObject {

    int POS_X = 2;

    // returns the current x coordinate of gameObject
    int getX() {
        return POS_X;
    }
}

static class Thing extends gameObject {

    int POS_X = 3;

    // returns the current x coordinate of gameObject
    int getX() {
        return POS_X;
    }
}

public static int difference(gameObject a, gameObject b) {
       return (a.getX() - b.getX());
}

public static void main(String[] args) {
    int d = difference(new Alien(), new Thing());
    System.out.print(d);
}

}

Note that all those classes are inner classes to the TestStackOverflow one and are accessed from the main static method so in this case, they should be static. Now regarding your code, there are some good practices that could be used in order to avoid any strange behavior:

  • I would implement every class in their own file, so no need to be static.
  • Define visibility of the class components. For instance, make POS_X private in every class and make reference to it with this, so you're making sure you are using this very field.
  • Also (just for naming convention sake) all class should be capitalized.
  • gameObject class should be an interface or an abstract class instead of a concrete class if is not going to be instantiated. It seems to me that the only goal for this one is to, either generalize the use of their child classes in external methods, or provide a default definition for getX().
  •  Tags:  
  • java
  • Related