【问题标题】:Accessing Child class instance method from Parent type child class object Java从父类型子类对象Java访问子类实例方法
【发布时间】:2021-03-01 11:56:37
【问题描述】:

如果我的问题看起来有点模棱两可,我深表歉意,我知道以前有人问过这个问题,但我的情况与我所读到的情况大不相同。

我正在寻找一种简单、优雅的解决方案,而不是复杂的解决方法。

我正在编写 RPG 代码,但在处理库存/物品系统时遇到了障碍。这是我的对象结构(不确定这是否是正确的术语),首先是英文,然后是一些示例代码。

一个 Player 类有一个 Inventory 类型的实例变量。

Inventory 类有一个 Item 对象数组,它们表示存储在库存槽中的物品。

Item 类有子类,例如 Weapon、Armour、Potion 等。

我不知道玩家将拥有什么物品,所以物品栏是用物品对象初始化的,但是当玩家拿起一把剑时,例如一个新的武器(ID)对象被创建并存储在物品栏中,我如果不对每个调用方法进行类型转换,仍然无法访问武器变量或方法。这通常不是什么大问题,但由于有 20 多个 Item 子类,总共有 100 个不同的变量和方法,因此每次 Typecast 所需的代码都非常庞大。

如果(你认为没有问题,那就是它的完成方式){

告诉我

} else if(你有更好的方法){

告诉我。

}

谢谢!

Player--has--Inventory--has--Item--hasChildren--武器/盔甲。

下面是一个片段,以显示我现在拥有的东西。注意:每个类都有明显更多的变量和方法,仅显示感觉重要的部分。

class Player {
   private Inventory inventory = new Inventory();
   public Item getInventoryItem(int slot){
      return inventory.getItemFromSlot(slot);
   }
}

class Inventory {
   private Item[] item;
   public Inventory() {
      this.item = new Item[INVENTORY_SIZE];
   }

   public Item getItemFromSlot(int slot) {
      return item[slot];
   }

// called when i pick up ANY ITEM.
// having a addWeapon(Weapon weapon) would make no difference (see end of code)
   public addItem(int slot, Item item) {
      inventory[slot] = item;  
   }
}

class Item {
   private int itemID;
   private int itemType;
   private String itemName;

   public Item(int ID) {
      this.itemID = ID;-
      this.itemName = getItemName(ID); //access a database which holds all item data
      this.itemType = getItemType(ID); //access a database holding all item types
   }
}

class Weapon extends Item {
   private int damage;

   public Weapon(int ID) {
      super(ID);
      this.damage = getWeaponDamage(ID);
   }

   public getDamage(){
      return damage;
   }
}

PROBLEM:

class Game {

//lets assume i have picked up a Weapon and it is now stored in slot i, as a Weapon not as an Item.

int test = player.getInventoryItem(i).getDamage(); //doesn't work, even when the item (i) class IS weapon
int test = ((Weapon)player.getInventoryItem(i)).getDamage(); //works
}

【问题讨论】:

  • 您的项目对我来说几乎就像一个枚举? enum Item { WEAPON, ARMOR, POTION }
  • 为什么 Weapon 类不扩展 Item 类?
  • @R4yY,它是 - 我刚刚更新了示例代码以反映这一点。

标签: java oop inheritance polymorphism parent-child


【解决方案1】:

如果你想访问特定于武器的方法或变量,你必须将项目列表元素转换为武器,如果你想使用多态类项目必须具有该方法或变量,因此可以为每个项目调用它.

【讨论】:

    【解决方案2】:

    在这种情况下需要强制转换,因为类Item 没有方法getDamage()。调用getInventoryItem() 返回一个Item,而不是Weapon,因此父类对其子类的方法一无所知。一种可能的解决方案是使用此处提到的自类型模式: Avoid casting in inherited java-classes

    【讨论】:

      【解决方案3】:

      所以我自己一直在测试一些东西。因为编译器认为getInventoryItem() 总是会返回一个Item,所以它不允许调用getDamage() 方法。但是当getInventoryItem() 引用的对象是Weapon 时,如果我简单地将int getDamage(){return -1} 添加为Item 类的方法,我仍然会从Weapon 中获得正确的int damage 值,并从其他任何东西中获得-1。完美!

      【讨论】:

      • 这是可能的解决方案,但将来可能很难维护代码。考虑到每种物品类型,如武器、任务物品、盔甲,仅针对它们的情况都有自己的属性。要么你会为所有类型做这件事,得到大量没有功能的代码,要么你会有不一致的结构。也许您应该考虑其他解决方案,例如通过使用工厂模式或类似的方式获取对象来实例化对象。想想吧。
      • @RavenDark - 所以我明白,逻辑是:从库存中读取我想要的对象的 itemID。使用 itemID,确定它是什么类型的对象。创建该对象的第二个实例,调用我想要的方法,然后丢弃该对象?我没想到。
      • 这是正确的方向。您可以通过省略两次创建实例来改进它。也许您可以存储在库存项目 ID 中,而不是项目。但我不知道你的要求。我宁愿进行强制转换,也不愿创建不必要的代码或两次持有对象。这会让你付出代价。另一种方法是检查instance of。您可以将项目存储在您的数组中,并检查项目的种类以使用工厂模式获取它。例如。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-28
      • 2021-11-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多