nialna2
nialna2

Reputation: 2224

Choose a type from a list

I have multiple classes that all inherit from the same Block class, and want to instantiate one of them based on a variable value.

Here is what I did for now:

public enum MapCases {
    FLOOR (Floor.class), // These are all subclass of my Block class
    WALL (Wall.class),
    ROCK (Rock.class);

    private Class<?> blockType;

    MapCases (Class<?> pointing) {
        this.block = pointing;
    }

    public Class<?> getType () {
        return this.blockType;
    }
};

Then later, I try to instantiate them given some data:

    private Block[] blocks; // Array of the mother type
    ...
    blocks = new Block[data.length]; // data is an int array
    for (int i = 0; i < data.length; i++) {
        int choice = data[i];
        Class<?> blockType = MapCases.values()[choice].getType();
        blocks[i] = new blockType(); // blockType is of unresolved type
    }

But Eclipse shows me an error saying it can't resolve blockType to a type (which seems logical given the fact that java don't know yet the type).

How could I achieve what I am trying to do?

Upvotes: 1

Views: 55

Answers (2)

Paul Bellora
Paul Bellora

Reputation: 55213

You shouldn't need reflection to do this. Consider this instead:

public enum MapCases {
    FLOOR {
        @Override
        public Block makeBlock() {
            return new Floor();
        }
    },
    WALL {
        @Override
        public Block makeBlock() {
            return new Wall();
        }
    },
    ROCK {
        @Override
        public Block makeBlock() {
            return new Rock();
        }
    };

    public abstract Block makeBlock();
}

In this case, the enum itself acts as the factory instead of the Class token it was holding.


Note that if you did want to stick with the Class token, it should be typed as Class<? extends Block>, as Elliott Frisch points out in the comments. Then a call to blockType.getConstructor().newInstance(), which GGrec's answer demonstrates, will return an instance of Block.

Upvotes: 3

Georgian
Georgian

Reputation: 8960

Use reflection to create a new instance from the class blueprint.

Pattern:

Class.forName(className).getConstructor().newInstance();

Your case:

blocks[i] = blockType.getConstructor().newInstance();

Upvotes: 2

Related Questions