简体   繁体   中英

How to pass type of object to class?

I am currently making a game in java using slick2D. The game is tile based and I am trying to make the random map generation. I am generating a room and the a hallway attached to that room and keep doing that until the map is all filled up. I have methods such as

generateRoom(int x, int y, int width, int height)

My question is how do I pass in the type of Tile that I want to use in the room. I thought it could look something like this

generateRoom(StoneTile, int x, int y, int width, int height)

Obviously this does not work. I do not want to send in an actual tile that has already been created because each tile has a specific location in it and when calling the method I do not know the location of the tiles. How would I just send in the type that is to be used in the method?

You probably just want to send the Class so use something like this:

generateRoom(Class tileClass, int x, int y, int width, int height)

And then you can call it using the getClass() method on your object.

It depends on exactly what you want to do with that type information. It sounds like you want to create new objects of the given type without knowing what that type is at compile-time. This means that Java Generics, which can be used to add type information to a method like this:

<T> generateRoom(int x, int y, int width, int height)

would not work, since you can't write new T() . (The Java compiler erases generic information before runtime).

So you could try using Reflection in combination with Generics, in which case you can pass in a Class object to your method and use Java's Reflection utilities to find a constructor for the class you give it.

<T> generateRoom(Class<T> tileClass, int x, int y, int width, int height) {
    Constructor<T> constructor = tileClass.getDeclaredConstructor(Arg1Type.class, Arg2Type.class);
    T tile = constructor.newInstance(arg1, arg2);
}

See here and here for more information on using reflection with Constructor.

Alternatively, if you don't want to risk the fragility of reflection, you could use the Factory Pattern and pass your method a Factory to construct the appropriate Tile:

generateRoom(TileFactory tileFactory, int x, int y, int width, int height) {
    Tile myTile = tileFactory.getInstance();
}

In order to do this you need to have an interface Tile that all of your tile types implement, and an interface TileFactory that each concrete tile factory (ie StoneTileFactory) implements. Then when you call the method, if you want it to create StoneTiles, you can give it a StoneTileFactory (which fits the TileFactory parameter type).

Of course, even this can be parameterized with Generics if you don't want to use interfaces:

<T> generateRoom(TileFactory<T> tileFactory, int x, int y, int width, int height) {
    T tile = tileFactory.getInstance()
}

In this case you would need to make each instance of TileFactory implement TileFactory<TileType> , such as TileFactory<StoneTile> , and parameterize the factory's getInstance method appropriately ( public T getInstance() ).

I think a simple approach that fits your needs is to create an enum that represents the tile types:

public enum TileType {
    STONE,
    WATER,
    FIRE,
    GRASS
}

You can then pass the type via your method like so:

TileType type = TileType.STONE;
generateRoom(type, x, y, width, height);
(...)

If you later need to add parameters or behavior for each tile type enums go a long way to accomodate this.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM