0

I'm making a game in Java and I'm working on the tilemap system for the game. I have a method in the Map class that will create a tile at certain x,y coordinates and I have an abstract Tile class which is then extended in each specific tile (e.g class DirtTile extends Tile).

The class Map would look something like this:

public class Map {
   int width,height;
   Tile[][] map;
   public Map(w,h) {
      width=w;
      height=h;
      map = new Tile[w][h];
   }
   void set(T type) {
      // type would be some subclass of Tile
      this.map[i][j] = new type(x,y);
   }
}

If need be, I can pass in a String or int to signify what the type of the tile should be, but I'd rather not get into an endless series of switch statements (and it would be hell to make changes to).

pythag0ras_
  • 122
  • 11
  • 1
    Please include the rest of the class you are trying to write, or at least the attribute `map` you are trying to fill. (Also the generic types of the class, if present). But truth be told, I suspect, you are trying to do something that is not possible, – TreffnonX May 14 '21 at 05:47
  • `void set(Class type);` ? – Fenio May 14 '21 at 05:57
  • Does this answer your question? [Create instance of generic type in Java?](https://stackoverflow.com/questions/75175/create-instance-of-generic-type-in-java) – luk2302 May 14 '21 at 06:05
  • @Fenio I saw that, but I wasn't sure how to instantiate an element of that type. I tried just doing new type(x,y) but it didn't work. – pythag0ras_ May 14 '21 at 06:06
  • To instantiate an element of that type, you create an object instance and place it into the map. I wrote it out for you below. – Shaan K May 14 '21 at 06:23
  • 1
    In order to instantiate `Class` you will have to use Java Reflection API. Grab constructor of the class and use `createInstance` method. – Fenio May 14 '21 at 06:29
  • I tried doing this: ` Class>[] type = {c}; Constructor> constructor = c.getConstructor(type); Object[] obj = {worldCoords.x, worldCoords.y}; map[arrCoords.x][arrCoords.y] = (T) constructor.newInstance(obj); ` but all I got was a NoSuchMethodException. – pythag0ras_ May 14 '21 at 06:42
  • 1
    Why is this `Map` (that's a dangerous name, by the way, as it conflicts with the core `java.util.Map`) responsible for _instantiating_ the tiles? With your description, it sounds like each individual tile would be a different type depending on its contents, so the `Map` itself should just deal with basic `Tile`s. It seems like you're putting responsibility in the wrong place. – chrylis -cautiouslyoptimistic- May 14 '21 at 06:43
  • @chrylis-cautiouslyoptimistic- I suppose it doesn't need to be here that it happens, but I still think I would need to be able to have a variable type *somewhere.* I might be wrong, though. – pythag0ras_ May 14 '21 at 06:52
  • Java does that for you, for every object. Unless you're constraining your map to be all of a single type of tile (which is what generics are for), then you just use the common base type `Tile` and call it a day. – chrylis -cautiouslyoptimistic- May 14 '21 at 06:55

2 Answers2

3

Reflection could be used in this case

<T extends Tile> void set(Class<T> type) {
    // type would be some subclass of Tile
    this.map[i][j] = type.newInstance();
}
Ahmed HENTETI
  • 1,108
  • 8
  • 18
0

In order to 'set' the tile to be a certain type, you must create an instance of an object to be placed there. The following will accomplish that for you:

If You did something like this you can pass any object that is or extends Tile as a parameter and just add it into the map.

public class Map {
    int width,height;
    Tile[][] map;

    public Map(width,height) {
       this.width=width;
       this.height=height;
       this.map = new Tile[w][h];
    }

    public <T extends Tile> void set(T tile) {
        // Whatever i and j values you want
        this.map[i][j] = tile;
    }
}

So now you can do something like the following:

Map m = new Map();
Tile a = new Tile(/* Initialize the values */);
DirtTile b = new DirtTile(/* Initialize the values */);

m.set(a);
m.set(b);

If you just want to set a tile to be a certain type you can do the following:

Map m = new Map();
m.set(new DirtTile());
Shaan K
  • 356
  • 1
  • 7
  • This isn't exactly what I'm trying to do. I need to be able to pass the class as an argument, not an instance of that class. – pythag0ras_ May 14 '21 at 06:25
  • @pythag0ras_ why? – qutax May 14 '21 at 06:34
  • @qutax When I create a tile, I need to specify the type. So, when I call the set() method, I need to tell it what the type of the tile needs to be. – pythag0ras_ May 14 '21 at 06:41
  • 1
    But why can't the caller of the method do that by creating an instance of the type instead of passing the type/class of it? In the end it doesn't matter if you are passing the type/class or an actual instance, except for some reason the caller of `set` hasn't access to the class's constructor or can't pass all required arguments to it. Is that the case? – qutax May 14 '21 at 07:07