简体   繁体   中英

Accessing Child class instance method from Parent type child class object Java

I apologise if my question seems a little ambiguous, and I know its been asked before but my circumstances are significantly different from what I've read.

I'm looking for a SIMPLE, ELEGANT solution, not a complex workaround.

I'm working on coding an RPG, and ran into a snag while working on the inventory/item system. Here is my object structure(not sure if that's the correct terminology) in English first, and some example code second.

A Player class has an instance variable of type Inventory.

The Inventory class has an array of Item objects, that represent an item stored in an inventory slot.

The Item class has children such as Weapon, Armour, Potion etc.

I don't know what item the player will have, so the Inventory is initialised with Item objects, but when the player picks up a sword for example a new Weapon(ID) object is created and stored in the inventory, i still can't access the Weapon variables or methods without Typecasting every calling method over. This wouldn't normally be too much of an issue but with 20+ Item subsclasses totalling 100's of different variables and methods, they code required would be enormous to Typecast every time.

if (you see no problem and that's how its done) {

let me know

} else if (you have a better way of doing this) {

let me know.

}

Thanks!

Player--has--Inventory--has--Item--hasChildren--Weapon/Armour.

Below is a snipped to show what i have right now. NOTE: There is significantly more variables and methods for each class, just showing what feels important.

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
}

如果要访问武器特定的方法或变量,则必须将 Item 列表元素强制转换为武器,如果要使用多态,则类项必须具有该方法或变量,因此可以为每个项调用它。

Casting is necessary in this case because the class Item has no Method getDamage() . Calling getInventoryItem() returns an Item , not a Weapon , so the parent class does not know anything about the methods of its child. One possible solution would be using self-type pattern mentioned here: Avoid casting in inherited java-classes

So I've been testing some things myself. Because the compiler THINKS getInventoryItem() will always return an Item, it doesn't allow for the method getDamage() to be called. But when the object referenced by getInventoryItem() is a Weapon, if I simply add int getDamage(){return -1} as a method of the Item class, I still get the correct int damage value from Weapon, and a -1 from anything else. Perfect!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM