Mam problem z używaniem argumentów typu w klasach języka Java. Mam jedną superklasę o nazwie 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;
}
}
Jest też moja klasa, która ją rozszerza
public abstract class OtherGame<T extends Player> extends Game<T> {
public OtherGame(GameEnum game, Player player1, T player2) {
super(game, player1, player2);
}
}
Jest też Class ChessGame, która rozszerza 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();
}
}
Teraz mam też kilka klas PlayerClass
public class Player implements Serializable {
public Player(String name, boolean player1) {
this.name = name;
this.player1 = player1;
}
}
I moja Computerclass, która rozszerza Playerclass
public abstract class Computer extends Player {
public Computer() {
super("Computer", false);
}
}
I mam ChessComputerclass, która rozszerza klasę Computerclass
public class ChessComputer extends Computer {
public ChessComputer() {
super();
}
}
Mam wtedy klasę, która wywołuje konstruktora ChessGameclass w następujący sposób:
new ChessGame<ChessComputer>(this.player);
//Here is no error
Dlaczego jest błąd, że nie ma takiego Konstruktora, ponieważ pomyślałem, że jeśli użyję zmiennej typu, takiej jak T, mogę dać Konstruktorowi dowolną podklasę tej, o której powiedziałem, że będzie rozszerzać. Wzywam również ChessGame Constructor za pomocą Typeargument ChessComputer, o którym myślałem, że „da” T klasę ChessComputer. Wiem trochę o Typearguments io tym, jak działają w Javie, ale oczywiście nie wystarczy.
Przepraszam, jeśli nie używam właściwych słów, aby to opisać, to dlatego, że angielski nie jest moim pierwszym językiem.
3 odpowiedzi
Tutaj struktura pary klas pochodnych klasy ma ogólne ograniczenie typu:
public class ChessGame<T extends Player> extends OtherGame<T>
public ChessGame(Player player) {
super(GameEnum.CHESS, player, new ChessComputer());
Trzeci parametr konstruktora OtherGame jest ograniczony do typu T, nawet jeśli jest to podtyp ChessComputer. Wymaga rzutu T, takiego jak super(GameEnum.CHESS, player, (T) new ChessComputer());
Z drugiej strony, jak skomentował @jrook, użycie typu ogólnego nie jest tutaj odpowiednie, jeśli nie masz innych planów. Powinieneś rozważyć użycie interfejsów jako klasy Player implementującej wspólny interfejs IPlayer i możesz przekazać podklasy do konstruktorów innych klas.
public interface IPlayer
Następnie zaimplementuj go w klasie Player i usuń wszystkie typy ogólne..
Rozszerzanie klas ogólnych o inne typy generyczne jest problematyczne. Nie chodzi o to, że twój kod jest zły, ale kompilator może zrobić tylko tyle, aby go ocenić, a użycie generyków w Javie nie jest idealne.
Najlepszym rozwiązaniem, jakie znalazłem, jest próba ograniczenia poziomu odniesienia do typów ogólnych do bieżącej klasy lub może jednego super. Poza tym są problemy.
To rozwiązuje problem:
public class ChessGame<T extends Player> extends OtherGame<Player>
Myślę, że mam „dobre” rozwiązanie,
Zmieniłem Konstruktora mojej klasy ChessGame
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();
}
}
I zadzwoń do Konstruktora jak
new ChessGame<Computer>(this.player, new ChessComputer());
Nadal muszę rzucić gracza, ale ponieważ jest to rzut obronny, myślę, że nie ma się czym martwić.
new ChessComputer()
jako parametru super()
. Bez znajomości zachowania Twojego kodu nie jest łatwo zrozumieć, co chcesz osiągnąć. Interfejsy są w rzeczywistości najlepszą praktyką wzorca abstrakcji projektu OOP, niezależnie od generowania. Dobrym pomysłem byłoby również zapoznanie się z wzorcami projektowania oprogramowania link
Podobne pytania
Nowe pytania
java
Java to język programowania wysokiego poziomu. Użyj tego tagu, jeśli masz problemy z używaniem lub zrozumieniem samego języka. Ten tag jest rzadko używany samodzielnie i jest najczęściej używany w połączeniu z [spring], [spring-boot], [jakarta-ee], [android], [javafx], [hadoop], [gradle] i [maven].
this.player
?ChessGame<ChessComputer>
brał tylkoChessComputer
jako argument konstruktora, musisz zdefiniować parametr konstruktora wChessGame
za pomocą typuT
:public ChessGame(T player)
.