Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/313.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
带有类型参数的Java类_Java_Subclass_Extends_Generic Type Argument - Fatal编程技术网

带有类型参数的Java类

带有类型参数的Java类,java,subclass,extends,generic-type-argument,Java,Subclass,Extends,Generic Type Argument,我在Java类中使用类型参数时遇到问题。 我有一个名为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.playe

我在Java类中使用类型参数时遇到问题。 我有一个名为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;
   }
}
还有我的电脑课,它扩展了Playerclass

public abstract class Computer extends Player {
    public Computer() {
        super("Computer", false);
    }
}
我有一个chesscomputer类,它扩展了computer类

public class ChessComputer extends Computer {
    public ChessComputer() {
        super();
    }
}
然后我有一个类,它调用ChessGame类的构造函数,如下所示:

new ChessGame<ChessComputer>(this.player);
//Here is no error
新棋类游戏(this.player);
//这里没有错误
为什么没有这样的构造函数是错误的,因为我想如果我使用一个类型变量,比如T,我可以给构造函数任何我说过它将扩展的子类。 我还使用类型参数ChessComputer调用ChessGame构造函数,我认为它会“给”T类ChessComputer。 我对Typearguments以及它们在Java中的工作原理略知一二,但显然还不够


很抱歉,如果我没有使用正确的词语来描述它,那是因为英语不是我的第一语言。

这里,类派生类对的结构有一个泛型类型约束:

public class ChessGame<T extends Player> extends OtherGame<T>
    public ChessGame(Player player) {
        super(GameEnum.CHESS, player, new ChessComputer());
公共类棋类游戏扩展了其他游戏
公共棋类游戏(玩家){
超级(GameEnum.CHESS,player,新的ChessComputer());
OtherGame构造函数的第3个参数被严格限制为类型T,即使它是chesComputer的子类型。它需要像
super(GameEnum.CHESS,player,(T)new chesComputer());


另一方面,正如@ JROOK评论的那样,如果没有其他计划,使用泛型类型不是很合适。您应该考虑使用接口作为播放器类来实现一个常见的iFlayer接口,并且可以将子类传递给其他类的构造器。

< P>用其他泛型扩展泛型类是有问题的。这并不是说你的代码是错误的,而是编译器只能对它进行这么多的评估,而且java对泛型的使用并不完美

我找到的最佳解决方案是尝试将泛型类型引用的级别限制为当前类,或者限制为一个超级类。除此之外还有问题

这就解决了问题:

public class ChessGame<T extends Player> extends OtherGame<Player>
公共类棋类游戏扩展了其他游戏
我想我有一个“好”的解决方案

我更改了棋类的构造函数

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();
    }
}
公共类棋类游戏扩展了其他游戏{
公共棋类游戏(玩家,T玩家2){
超级(GameEnum.CHESS、玩家、玩家2);
if(计算机的super.player2实例){
((计算机)super.player2).setInput(这个棋盘);
}
this.playerFile=新文件(CHESSGAME,String.format(“%s vs.Computer%s”,super.player1,FILEEXT));
this.comFile=新文件(CHESSGAME,super.player1.hashCode()+);
这个.gameMenu();
}
}
然后像这样调用构造函数

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

我仍然需要对玩家进行施放,但由于它是一个保存施放,我想没有什么好担心的。

如何定义
这个.player
变量?如果你想
棋盘游戏
只使用
棋盘计算机
作为它的构造函数参数,那么你必须用t在
棋盘游戏
中定义构造函数参数他
T
类型:
公共棋类游戏(T玩家)
。在我的程序启动时,用户会被提示给出一个名称,这样我就可以创建一个普通玩家,然后他可以决定单独与计算机或其他玩家玩游戏。可以在github或其他一些公共repo上共享您的代码,这样人们就可以克隆代码并查看所有代码和错误。我希望棋类游戏可以使用棋盘计算机或其他计算机玩家。我已经试过了,但是它比从CaseStudio到T.的未选中的CaseTunes,这就是我想要避免的。是的,这是一个问题,我建议在上面考虑使用接口。定义一个播放器接口。<代码>公共接口iPlayer < /Cord>。然后在播放器类上实现它,并移除所有泛型类型。接口是GOO。d主意,但我必须在播放器和Computer类中实现相同的函数,这不是我想要的,因为它们有不同的函数。是的,你看到了吗,你实际上以错误的方式使用了
new chesComputer()
作为
super()的参数
。如果不知道代码的行为,就不容易理解您想要实现的目标。接口实际上是OOP设计中抽象模式的最佳实践,无论泛化如何。另外,看看软件设计模式也是个好主意。这不是我想要的,我不想有一个当我在Singleplayermode时,ch接受两个播放器,我希望一个播放器和构造函数将计算机交给超级构造函数。如果我使用IPlayer接口,播放器和计算机必须实现相同的方法,但它们并不真正共享任何方法。
public class ChessGame<T extends Player> extends OtherGame<Player>
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();
    }
}
new ChessGame<Computer>(this.player, new ChessComputer());