0

I'm implementing a board game for two players. Users are able to create their own AIs for the game and add them to the game. These AIs also can implement own, more efficient versions (data structures) of the board to save time when calculating the next move. The HumanPlayer and a simple Board are implemented by me.

To be able to make moves on the different boards from a central Game class and check moves in a given Referee, all classes which shall interact with the board have to inherit from the abstract class Actor.

public abstract class Actor<BoardClass extends IBoard> {

    protected BoardClass board;
    
    public void makeMove(Move move) {
        board.movePiece(move);
    }
}

The referenced interface IBoard has to be implemented by any board used in the program. That way, the game will always be able to inform all registered instances of Actor about the made move via following method.

private void informActors(Move move) {
    for (Actor<?> actor : actors) {
        actor.makeMove(move);
    }
}

All implemented players - including the human player implemented by me - have to inherit from the abstract class Player which again has to inherit from the given class Actor.

public abstract class Player<BoardClass extends IBoard> extends Actor<BoardClass> {
    
    //some game specific code
}

The HumanPlayer now inherits from Player and uses my Board class as the type that implements IBoard.

public class HumanPlayer extends Player<Board> {

    // some game specific code
}

The exact implementation of my simple Board class and the Referee class do not matter.

To keep redundant code at a minimum, I don't want to instantiate the implementation of Board as the IBoard inheriting type in both the Referee and the Player class, especially since I was able to use interfaces and inherited methods to implement every other "interaction" dynamically.

So, to be precise. I am searching for a dynamic way of instantiating an object from a class, which is only known during runtime, but without using reflection.

I had the idea to create a static method in the IBoard interface which creates an object of that class and returns it and which gets overwritten by the implementing classes, but since static methods use static binding, they do not get bound dynamically during runtime.

The only other option I could think of was reflection, which I don't want to use.

I do know I can use

// replace 'ClassConstructor' with 'Referee', 'HumanPlayer' or any other class inheriting from 'Actor'.

public ClassConstructor() {
    this.board = new Board();
}

as the constructor of the Referee and the HumanPlayer, but again, it's bothering me to duplicate that line of code when its maybe possible via a better way.

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
  • You can look at `ServiceLoader` and implement this as an SPI, but indirectly you would still be using reflection, just not in your own code. – Mark Rotteveel Oct 21 '22 at 16:45
  • There's [`Class.newInstance()`](https://docs.oracle.com/javase/8/docs/api/java/lang/Class.html#newInstance--), but type erasure is working against you. You might need to parameterize things with `Class` passed about. You're asking how to build a car without using an engine. Instantiating things based on runtime knowledge is a pretty good definition of reflection. – Gene Oct 21 '22 at 17:04
  • @Gene I was hoping there would be a way to use dynamic binding like you do on overwritten methods. My idea rather was building a car while deciding which engine to use in the process of factoring depending on what the next customer wants. But I understand what you mean. Overall one could say, what I want isn't possible with the current state of JDK, right? –  Oct 24 '22 at 17:20

0 Answers0