0

So I have an ArrayList of objects. Inside those objects are various attributes and their values.

The code is pretty simple. GBox and GCircle are childs of GHP. The ArrayList is in World.

What I want to do is print the HP and volume of the box and the HP and diameter of the circle. I understand I could override toString() but I actually want to get the values. What's the correct syntax to do so?

//Main.java
public class Main {
    public static void main(String[] args) {
        Ini i = new Ini();
    }
}

//Ini.java
public class Ini {
    private static World w;

    public Ini() {
        w = new World;
        w.makeGBox();
        w.makeGCircle();
        System.out.println("Box: HP: " +
                           w.getList().get(0).getHP() +
                           "Volume: " +
                           w.getList().get(0).GBox.getVolume());
                           //compile error no variable GBox in GHP
        System.out.println("Circle: HP: " +
                           w.getList().get(1).getHP() +
                           "Radius: " +
                           w.getList().get(1).GCircle.getRadius());
                           //compile error no variable GCircle in GHP
    }
}

//World.java
import java.util.ArrayList;

public class World {
    private ArrayList<GHP> list = new ArrayList<>();

    public void makeGBox() {
        list.add(new GBox());
    }
    public void makeGCircle() {
        list.add(new GCircle());
    }

    public ArrayList<GHP> getList() {
        return list;
    }
}

//GHP.java
public class GHP {
    private int HP;

    public GHP() {
        setHP(5);
    }

    public int getHP() {
        return HP;
    }
    public void setHP(int HP) {
        this.HP = HP;
    }
}

//GBox.java
public class GBox extends GHP{
    private int volume;

    public GBox() {
        setVolume(10);
    }

    public int getVolume() {
        return volume;
    }
    public void setVolume(int volume) {
        this.volume = volume;
    }
}

//GCircle.java
public class GCircle extends GHP{
    private int radius;

    public GCircle {
        setRadius(7);
    }

    public int getRadius() {
        return radius;
    }
    public void setRadius(int radius) {
        this.radius = radius;
    }
}
user2837858
  • 339
  • 6
  • 18

5 Answers5

1

Apart from the many compilation problems, you need these changes to achieve what you want.

for (GHP ghp : w.getList()) { // Avoid using get(index) without a forloop, as such
    if (ghp instanceof GBox) { // Using the instanceof operator, you can differentiate the 2 class types
        System.out.println("Box: HP: " + ghp.getHP() + "Volume: "
                + ((GBox) ghp).getVolume()); // Cast it to GBox to be able to call getVolume
    }

    if (ghp instanceof GCircle) {
        System.out.println("Circle: HP: " + ghp.getHP() + "Radius: "
                + ((GCircle) ghp).getRadius());// Cast it to GCircle to be able to call getRadius 
    }
}
Rahul
  • 44,383
  • 11
  • 84
  • 103
  • May I ask you something? I'm now trying to set the box's volume as the current volume + 5. I tried `(((GBox) ghp).getVolume()) += 5` but this does not work for obvious reasons. What is the correct way to do this? – user2837858 Oct 04 '13 at 09:20
  • Shouldn't you set the volume for that, like this. `((GBox) ghp).setVolume(currentVolume + 5));` – Rahul Oct 04 '13 at 09:27
0

You would need to cast the generic GHP reference to the specific type like:

((GCircle) ghp).getRadius()

You might also want to have a look on instanceof operator.

The idea being:

  • for output you override the toString() method because you don't need any class specific information, just print out object details

  • for class-specific operations you downcast to he specific type

Jan Zyka
  • 17,460
  • 16
  • 70
  • 118
0

When you read the list values, the only thing the compiler knows, is that the list contains GHP instances.

First check the type and then cast it to the subclass.

GHP ghp = w.getList().get(0);
if(ghp instanceof GBox) {
  GBox gbox = (GBox) ghp;
  // Here you can access the method getVolume()
  /* ... */  gbox.getVolume();
}
vanje
  • 10,180
  • 2
  • 31
  • 47
0

A cleaner, more OOP alternative to adding methods to the base class and/or instanceof checks is to use the Visitor pattern that allows you to separate your object structure from any algorithms that operate on them. The algorithm in this case is simply a "display" algorithm.

That said, for most simple cases (like this one) adding methods to the base class and overriding or using instanceof is fine.

pillingworth
  • 3,238
  • 2
  • 24
  • 49
0
List<Shape> shapes = new ArrayList<Shape>();    

.... ...

for (Shape shape : shapes) {
            System.out.println(shape.getHp());
            if(shape instanceof Circle){
                System.out.println(((Circle) shape).getValuem());
            }else if(shape instanceof Box){
                System.out.println(((Box) shape).getHieght());
        }

try this way..

Chowdappa
  • 1,580
  • 1
  • 15
  • 31