[英]How do I check which subclass was passed into a constructor?
我對 Java 和編程比較陌生,所以如果這個問題看起來很愚蠢,我深表歉意。 我正在為 Java 編程類創建一個戰斗游戲——我有一個帶有一些基本方法的 Hero 類和一個擴展 Hero 但添加了自己獨特方法的子類 Paladin。我想要一個 Battleground 對象,它可以傳入 ANY Hero 類,然后檢查傳入的是哪個特定子類。如何確定傳入的是哪個 Hero 子類?
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 語句是一個占位符偽代碼,只是為了闡明我的意思。
public class Battleground {
private Hero player;
public Battleground (Hero player) {
this.player = player;
}
public void startRound() {
// HERE!!
if (player.equals(Paladin)) {
player.heal();
}
}
}
考慮到您的職業實際建模的內容,對於戰場來說,知道聖騎士在回合開始時會自我治療並沒有多大意義,戰場也沒有責任確保聖騎士自我治療。
一個更明智的設計是讓游戲通知英雄回合已經開始,並讓特定的Hero
子類控制該回合開始時那種英雄的行為。 例如:
public class Hero {
// ...
public void onRoundStart() {
// do nothing
}
}
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();
// ...
}
}
這樣你就不需要任何if
語句或instanceof
檢查,而且定義 Paladin 行為的代碼也在它合理所屬的Paladin
類中。 如果以后想更改聖騎士的規則,更容易知道需要編輯哪個職業。
這種重構被稱為“ 用多態替換條件”。
使用 instanceof 可以被認為是一種代碼異味——這意味着一種不好的做法。 有一個替代方案供您考慮。
將heal()
方法添加到Hero
類,但將實現留空。
在Paladin
類中只放置一個實現。 然后,即使所有玩家都會調用heal()
,它只會在Paladins
內部執行某些操作。
但是...如果您仍然需要檢測類類型...
有多種方法可以區分類別。 實例為一。 另一個是有不同的構造函數。 第三個是有一個名為 EntityType 的 ENUM 或 String 字段。
在您的情況下,我認為instanceof
或使用special field
最有意義。
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;
}
}
檢測類型
您將在兩個類中都有一個名為getHeroType()
。
if(hero.getHeroType == Hero.PALADIN_HERO){
}else if(hero.getHeroType == Hero.BASIC_HERO){
}
如果需要,您可以使用來檢查對象的類:
if (player instanceof Paladin)
毫無疑問,這會奏效。 如果您沒有很多“特殊”行為和有限的少量案例,那可能是一個合理的解決方案。 但是假設你的游戲最終會對Hero
每個子類進行很多特殊處理,而且可能不僅僅是在你的Battlefield
類的startRound()
方法中,你的代碼有一天會被這些instanceof
檢查startRound()
混亂。 同樣適用,如果您在Hero
類中使用特定類型字段。
在這種情況下,更好的解決方案可能是將邏輯重新定位到特殊類中,並在可能的情況下盡量避免類型檢查,或者至少在必要時為它們提供一個明確定義的位置。
更新:刪除了錯誤的演示實現
你總是可以做player.getClass
來獲得實際的類。 至於if
語句,您可以使用instanceof
運算符。
所以
if (player instanceof Paladin) {
((Paladin)player).heal();
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.