泛型和通配符的大多数示例涉及集合,但我正在尝试学习如何仅使用类来使用它们。我想学习这种更现代的泛型方法,这样我就可以避免当子类重写超类中的方法时出现的笨拙的转换。
我有一个猜测游戏的抽象类,可能用于数字猜谜游戏,猜词游戏,甚至是Mastermind。游戏包中包含Level和Score的抽象类。然后,我想将猜测游戏子类化,并将级别和分数子类化,以制作特定的游戏。
以下是分数的抽象类:
// a score is a measure of how close a guess is to being correct
public abstract class Score{
public abstract boolean equals(Class<? extends Score> otherScore);
public abstract boolean isWin(Class<? extends Level> level);
}
在编写isWin的参数时,我试图说:期望获得一个Level或Level子类的参数。
然后我创建了分数为Mastermind的子类:
public class MastermindScore extends games.Score{
int numRightPlace;
int numWrongPlace;
public MastermindScore(int numRightPlace, int numWrongPlace){
this.numRightPlace = numRightPlace;
this.numWrongPlace = numWrongPlace;
}
public boolean equals(MastermindScore otherScore){
if (this.numRightPlace==otherScore.numRightPlace){
if (this.numWrongPlace == otherScore.numWrongPlace){
return true;
}
}
return false;
}
public boolean isWin(MastermindLevel level){
return this.numRightPlace == level.numSlots;
}
这不能编译,因为它认为我没有正确地覆盖抽象超类所需的方法。因此,即使子类'isWin方法的参数是Level的子类,它也不会将其识别为期望的类型。
然后我将Level的子类的类声明行更改为:
public class MastermindLevel<T extends games.Level>{
public final int numColors;
public final int numSlots;
public MastermindLevel(int numColors, int numSlots, int maxGuesses){
super(maxGuesses);
this.numColors = numColors;
this.numSlots = numSlots;
}
}
但是,当我这样做时,对超类构造函数的调用不起作用,因为它认为我的类是Object的子类,而不是Level的子类。
我知道我可以通过使用超类的参数编写重写方法,然后将Level和Score转换为MastermindLevel和MastermindScore来获取代码,但我希望了解如何使用泛型来完成此操作。我真的想更全面地理解泛型。
感谢您的帮助。
答案 0 :(得分:3)
请注意,在抽象类Score
中,您的方法正在接受java.lang.Class
对象。
但是,在您的班级MastermindScore
中,您使用类型MastermindScore
和MastermindLevel
作为方法参数。这不会起作用,因为类型与超类中的类型不同,MastermindScore
不是Class<? extends Score>
等的子类。
做这样的事情:
public abstract class Score<S extends Score, L extends Level> {
public abstract boolean equals(S otherScore);
public abstract boolean isWin(L level);
}
public class MastermindScore extends Score<MastermindScore, MastermindLevel> {
public boolean equals(MastermindScore otherScore) {
// ...
}
// etc.
}
答案 1 :(得分:2)
你不能这样做,你的方法声明:
public abstract boolean isWin(Class<? extends Level> level);
表示您的方法需要Class
Type
Score
或某个子类。所以Score.class
可以作为参数。即你要求Class
不是它的实例。
所以你真正想要的是:
public abstract<L extends Level> boolean isWin(L level);
这是一种通用方法。但这并没有真正增加你的代码,因为当你使用L
时,所有编译器都可以说L
是Level
- 你仍然需要强制转换。
所以你真正需要的是通用interface
:
public interface Score<L> {
boolean isWin(L level);
}
当你创建其他实现时,你会这样做:
public class MastermindScore implements Score<MastermindLevel> {
你需要一个方法:
boolean isWin(MastermindLevel level);
显然MastermindLevel
需要extends Level
。
另请注意,equals
已实施为equals(Object other)
,因此必须强制转换。你不应该有equals(MyType other)
方法。