Java 如何检查哪个子类被传递到构造函数中?
我对Java和编程比较陌生,所以如果这个问题看起来很愚蠢,我很抱歉。我正在为一个Java编程类创建一个战斗游戏——我有一个包含一些基本方法的英雄类和一个子类Paladin,它扩展了英雄,但添加了自己独特的方法。我希望有一个战场对象可以在任何英雄类中传递,但要检查传递了哪个特定的子类。如何确定传入了哪些Hero子类Java 如何检查哪个子类被传递到构造函数中?,java,Java,我对Java和编程比较陌生,所以如果这个问题看起来很愚蠢,我很抱歉。我正在为一个Java编程类创建一个战斗游戏——我有一个包含一些基本方法的英雄类和一个子类Paladin,它扩展了英雄,但添加了自己独特的方法。我希望有一个战场对象可以在任何英雄类中传递,但要检查传递了哪个特定的子类。如何确定传入了哪些Hero子类 public class Hero { private String name; private int hitPoints; public Hero (String
public class Hero {
private String name;
private int hitPoints;
public Hero (String name, int hitPoints) {
this.name = name;
this.hitPoints = hitPoints;
}
public String getName() { return this.name; }
public int getHitPoints() { return this.hitPoints; }
public void takeDamage(int amount) { this.hitPoints -= amount; }
}
这是圣骑士职业
public class Paladin extends Hero {
public Hero (String name, int hitPoints) {
super(name, hitPoints);
}
public void heal(int amount) {
this.hitPoints += amount;
}
}
因此,在战场职业中,我有一种方法试图错误地检查通过的英雄是否是圣骑士。我该怎么做呢?if语句是一个占位符psuedo代码,只是为了澄清我的意思
public class Battleground {
private Hero player;
public Battleground (Hero player) {
this.player = player;
}
public void startRound() {
// HERE!!
if (player.equals(Paladin)) {
player.heal();
}
}
}
您可以始终执行player.getClass来获取实际类。至于if语句,可以使用instanceof运算符
所以
使用Instanceof有时被认为是一种代码味道
使用instanceof可以被认为是一种代码味道——这意味着一种糟糕的做法。
你可以考虑另一种选择。
将heal方法添加到Hero类,但将实现留空
在圣骑士类中只放置一个实现。然后,即使所有玩家都需要治疗,它也只能在圣骑士内部起作用
然而。。。如果仍然需要检测类类型
检测类的方法
有多种方法可以区分不同的类。
这是一个例子。
另一个是有不同的构造函数。
第三种方法是使用名为EntityType的枚举或字符串字段
在您的情况下,我认为instanceof或使用特殊字段最有意义
瞬间
使用特殊字段
速成英雄
。。。
}
快速示例圣骑士
检测类型
这两个类中都有一个名为getHeroType的方法
考虑到你的职业实际是什么,战场知道圣骑士在回合开始时会自行痊愈,或者战场负责确保圣骑士自行痊愈,这都没有多大意义 更合理的设计是让游戏通知英雄回合已经开始,并让特定的英雄子类控制该类英雄在回合开始时做什么。例如: 公众阶级英雄{ // ... 公开无效,重新开始{ //无所事事 } } 这样,您就不需要任何if语句或instanceof检查,而且定义一个圣骑士行为的代码也在圣骑士类中,它应该属于这个类。如果你以后想修改圣骑士的规则,你可以更容易地知道你需要编辑哪个职业
这种重构称为。如果需要,可以使用检查对象的类: 如果玩家是圣骑士 毫无疑问,这会奏效的。如果你没有太多的特殊行为和有限的少量案例,这可能是一个合理的解决方案。但是假设你的游戏最终会对英雄的每个子类进行大量的特殊处理,而且可能不仅仅是在你的战地类的startrond方法中,你的代码总有一天会被这些检查的实例弄得乱七八糟。如果在Hero类中使用特定类型字段,则同样适用 在这种情况下,更好的解决方案可能是将逻辑重新定位到特殊类中,并尽可能避免类型检查,或者至少在必要时为它们定义一个良好的位置
更新:删除了错误的演示实现player.heal将无法编译。你需要向圣骑士施放变量。或者添加一个在英雄类中不起任何作用的治疗实现,你甚至可以调用takeDamage-1*amount@cricket_007我不同意投票结果。区分类的方法不止一种。这是一个例子。另一个是有不同的构造函数。第三种方法是使用名为EntityType的枚举或字符串字段。关于后者,Joshua Bloch建议不要使用有效的Java创建自己的类型系统。您应该使用类型系统,而不是尝试引入自己的基于枚举/字符串值的getType系统@MenelaosBakopoulos@markspace的确几年前,我们曾制作过自己的类型系统,因为它被认为速度更快。我甚至记得在eclipse的AST节点中遇到过它。虽然这通常是一个很好的答案,但是BattleGroundHandler中的重载方法不太可能按照您期望的方式运行。要调用的方法在编译时根据对Hero的引用类型进行选择。例如,如果你写了英雄h=新圣骑士;然后是battlegroundHandlers.handleStartRoundh,将调用获取英雄的方法,而不是获取圣骑士的方法。你说得对,很好,谢谢。如果你想给出一个快速的答案,就会发生这种情况。不管怎样,不管具体的解决方案是什么,我想说的是 nt out是为了尽量避免代码被一堆instanceof检查或类似的检查弄得乱七八糟。
if (player instanceof Paladin) {
((Paladin)player).heal();
}
if(player instanceof Paladin)
public class Hero {
private String name;
private int hitPoints;
private int HeroType;
public Hero (String name, int hitPoints) {
this.name = name;
this.hitPoints = hitPoints;
this.heroType = BASIC_HERO;
}
public static int BASIC_HERO = 0;
public static int PALADIN_HERO = 1;
public class Paladin extends Hero {
public Paladin(String name, int hitPoints) {
super(name, hitPoints);
this.heroType = PALADIN_HERO;
}
}
if(hero.getHeroType == Hero.PALADIN_HERO){
}else if(hero.getHeroType == Hero.BASIC_HERO){
}
public class Paladin extends Hero {
// ...
@Override
public void onRoundStart() {
// your heal method takes an int as its argument
heal(10);
}
}
public class Battleground {
// ...
public void startRound() {
// let the particular Hero subclass control what happens
player.onRoundStart();
// ...
}
}