Joseph Erickson
Joseph Erickson

Reputation: 960

Intro to polymorphism 101 java

I'm making a small RPG. There is an Item class which is the parent of each item in the game. These items could be Potion (which is a class) or Bandage (which is a class).

The Item class looks like this:

public class Item
{
int qty;
String name;
Hero hero1;

public void passHero(Hero hero1)
{
    this.hero1 = hero1;
}

public void use()
{
    if(qty == 0)
    {
        System.out.println("You have no more of this item to use.");
    }
    else
    {    
        qty--;
    }
}

public void addInv(int value)
{
    qty = qty + value;
}
}

A method for passing in the Hero class. A method for using an item. A method for adding to the inventory of the item.

This method activates these item classes:

public void initializeItemInventory()
{
    items[0] = new Potion();
    items[1] = new Bandage();
}

And this method would theoretically print all the items and their quantities:

public void useInventory()
{
    for(int i = 0; i<items.length; i++)
    {
        System.out.println("Enter: " + i + " for " + items[i].name);

    }

    int response = input.nextInt();
    items[response].use();

}

The Potion class, as an example, has an instance variable like:

String name = "Potion";

So my question. Why isn't the name variable from Potion being called correctly in the useInventory method. It returns null which tells me it's returning the parent class Item name, and not the name of the individual subclass variables.

Upvotes: 0

Views: 190

Answers (2)

Marko Topolnik
Marko Topolnik

Reputation: 200138

public class Item
{
  int qty;
  String name;
  ...

The Item class already has name, and that's what you access from an Item-typed variable:

items[0].name

So if you have

public class Potion extends Item
{
  String name = "Potion";
  ...

then the Potion class has two name fields:

Potion p = new Potion();
System.out.println(p.name);
System.out.println((Item) p).name);

As you say, you want polymorphism, but it only applies to methods. Therefore you need a getter:

public class Item
{
  String name;
  public String getName() { return name; }
  ...

In the Potion subclass you may have

public class Potion extends Item
{
  public Potion() { this.name = "Potion"; }
  ...

and items[0].getName() will now work as expected.

Additional note

I'll add this to show a bit of the power of polymorphism.

If you happened to have the name property always the same for all the instances of the same class, you could easily refactor your getter-based solution by completely eliminating the need to store a name variable:

public class Item
{
  public String getName() { return "Generic item"; }
  ...

public class Potion extends Item
{
  @Override public String getName() { return "Potion"; }
  ...

Upvotes: 3

Flyaway
Flyaway

Reputation: 69

Instead of declaring a new variable in your subclass like "String name = "Potion";" Use your constructor to pass the value to your superclass, something like this:

// the Item supuerclass has one constructor
public Item(name) {
  this.name = name;
} 

// the Potion subclass has one constructor
public Potion() {
  super("Potion");
}

Upvotes: 2

Related Questions