1

I am having trouble using Type Arguments in Java Classes. I have one superclass named Game

public abstract class Game<T extends Player> implements Serializable {
    public Game(GameEnum game, Player player1, T player2) {
        this.timer = new Timer();
        this.game = game;
        this.player1 = player1;
        this.player1.setPlayer1();
        this.player2 = player2;
   }
}

Then there is my Class which extends it

public abstract class OtherGame<T extends Player> extends Game<T> {
    public OtherGame(GameEnum game, Player player1, T player2) {
        super(game, player1, player2);
    }
}

Then there is the Class ChessGame which extends the Class OtherGame

public class ChessGame<T extends Player> extends OtherGame<T> {
    public ChessGame(Player player) {
        super(GameEnum.CHESS, player, new ChessComputer());

        //Here is the Error that the Constructor with the Param. ChessComputer
        //does not exist and i can cast the ChessComputer to T.

        ((Computer) super.player2).setInput(this.chessboard);
        this.playerFile = new File(CHESSGAME, String.format("%s vs. Computer%s", super.player1, FILEEXT));
        this.comFile = new File(CHESSGAME, super.player1.hashCode() + "");
        this.gameMenu();
    }
}

Now I also have some PlayerClasses

public class Player implements Serializable {
    public Player(String name, boolean player1) {
        this.name = name;
        this.player1 = player1;
    }
}

And my Computerclass which extends the Playerclass

public abstract class Computer extends Player {
    public Computer() {
        super("Computer", false);
    }
}

And I have a ChessComputerclass which extends the Computerclass

public class ChessComputer extends Computer {
    public ChessComputer() {
        super();
    }
}

I have then a Class which calls the Constructor of the ChessGameclass as following:

new ChessGame<ChessComputer>(this.player);
//Here is no error

Why is there the Error that there is no such Constructor, because I thought if I use a TypeVariable, such as T, I could give the Constructor any Subclass of the one that I said it would Extend. I also call the ChessGame Constructor with the Typeargument ChessComputer of which I thought would "give" T the class ChessComputer. I know a little about Typearguments and how they work in Java, but obviously not enough.

I am sorry if I don't use the right Words to describe it, that's because English is not my first Language.

8
  • 1
    How is the this.player variable defined? Commented Nov 19, 2019 at 20:52
  • 1
    If you want ChessGame<ChessComputer> to only take a ChessComputer as its constructor argument, then you have to define the constructor parameter in ChessGame with the T type: public ChessGame(T player). Commented Nov 19, 2019 at 20:56
  • At my programmstart the User is prompt to give a name, so I can create a normal Player, then he can decide to play alone against the Computer or against an other player Commented Nov 19, 2019 at 20:56
  • Probably share your code on github or some other public repo, so people can clone it and see all the code and errors. Commented Nov 19, 2019 at 20:57
  • I want the ChessGame to take either a ChessComputer or a Player. Commented Nov 19, 2019 at 20:58

3 Answers 3

1

Here the structure of class-derived class pair has a generic type constraint:

public class ChessGame<T extends Player> extends OtherGame<T>
    public ChessGame(Player player) {
        super(GameEnum.CHESS, player, new ChessComputer());

OtherGame constructor's 3rd param is stricted to type T even if it is a subtype of ChessComputer. It needs cast of T like super(GameEnum.CHESS, player, (T) new ChessComputer());

On the other hand, as @jrook commented, using generic type is not well suited here if you don't have other plans. You should consider using interfaces as Player class implementing a common IPlayer interface and you can pass the sub classes to other classes' constructors.

Sign up to request clarification or add additional context in comments.

3 Comments

I have already tried that, but than it says unchecked Cast from ChessComputer to T. And that is what i want to avoid.
Yes that is an issue and I suggested above consider using interfaces. Define a player interface. public interface IPlayer Then implement it at Player class and remove all generic types..
The Interface was a good Idea, but then I have to implement the same functions in the Player and the Computerclass which is not what I want, because those have different functions all together.
1

Extending generic classes with other generics is problematic. It's not that your code is wrong, but the compiler can only do so much to evaluate it and java's usage of generics isn't perfect.

The best solution I've found is to try to limit the level of generic type reference to the current class, or maybe one super. Beyond that lies problems.

This resolves the issue:

public class ChessGame<T extends Player> extends OtherGame<Player>

Comments

0

I have a "good" Solution I would think,

I changed the Constructor of my ChessGame class

public class ChessGame<T extends Player> extends OtherGame<T> {
    public ChessGame(Player player, T player2) {
        super(GameEnum.CHESS, player, player2);
        if (super.player2 instanceof Computer) {
            ((Computer) super.player2).setInput(this.chessboard);
        }
        this.playerFile = new File(CHESSGAME, String.format("%s vs. Computer%s", super.player1, FILEEXT));
        this.comFile = new File(CHESSGAME, super.player1.hashCode() + "");
        this.gameMenu();
    }
}

And call the Constructor like

new ChessGame<Computer>(this.player, new ChessComputer());

I still have to cast the player but since it is a save cast there is nothing to worry about, I think.

2 Comments

Yeah do you see, you actually used in a wrong manner the new ChessComputer() as the parameter of the super(). Without knowing the behavior of your code not easy to understand what you want to achieve. Interfaces are actually the best practice of abstraction pattern of the OOP design regardless of the generifying. Also would be a good idea to have a look at the software design patterns link
This is not what i want, I dont want to have a constructor which takes in two Player when i am in Singleplayermode, I want one Player and the constructor to give the super Constructor the Computer. If i use an IPlayer interface the Player and the Computer have to implement the same Methods but they do not really share any methods.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.