Neil Ruggiero
Neil Ruggiero

Reputation: 340

Can only access Parent class variables from method

So the issue I'm running into is this. I've written a method as a part of a program that I'm using to display all the objects in an ArrayList. There are three different types of objects stored in this ArrayList: Fungus, Flowers and Weeds. I'm able to call plantList.get(i).getName() and plantList.get(i).getColor methods with no issue. Both of these variables belong to the parent class called Plant. However, when calling the following method plantList.get(i).getPoison() (this method belongs to the subclass Fungus) I get a compiler error saying that it cannot find the variable Fungus.

I've tried it with every other variable unique to a subclass, and the same things happens. So I can access variables from the parent class 'Plant' but not from any of the subclasses of 'Fungus' 'Flower' or 'Weed'. I'm new to using subclasses and superclasses so I'm having a hard time figuring out exactly where the issue is arising.

public static void displayPlant(ArrayList<Plant> plantList) {
    for (int i = 0; i < plantList.size(); i++) {
        System.out.print(plantList.get(i).getName());
        System.out.print(plantList.get(i).getID());
        System.out.print(plantList.get(i).getColor());
        if (plantList.get(i).contains(Fungus) == true) {
            System.out.print(plantList.get(i).getPoison());
        }
        else if (plantList.get(i).contains(Flower) == true) {
            System.out.print(plantList.get(i).getSmell());
            System.out.print(plantList.get(i).getThorns());
        }
        else {
            System.out.print(plantList.get(i).getPoison());
            System.out.print(plantList.get(i).getEdible());
            System.out.print(plantList.get(i).getMedicinal());
        }
    }
}

Upvotes: 2

Views: 953

Answers (3)

Krzysztof Atłasik
Krzysztof Atłasik

Reputation: 22595

Java is strongly typed language. That means that, if you want to use methods of child class you have to cast down to child class.

In your example:

...
else if (plantList.get(i) instanceof Fungus) { //check if plant is fungus
    System.out.print(plantList.get(i).getSmell());
    System.out.print(((Fungus)plantList.get(i)).getThorns()); //downcasting
}
...

Your check using constains wouldn't work. To check type of object you need to use operator instanceof.

Upvotes: 0

sanjeevjha
sanjeevjha

Reputation: 1549

Actually you are doing it in a wrong way,

Once you keep the object of child class into parent class variable then at compile time it search or find only the methods and variables that are declared in the parent class.

if you want to access the child class variables then you need to first find out the child class and then typecast it according

public static void displayPlant(ArrayList<Plant> plantList) {
    for (int i = 0; i < plantList.size(); i++) {
        Plant plant=plantList.get(i);
        if (plant instanceof Flowers) {
            Flowers fl=(Flowers)plant;
            //TODO do whatever you want to do
        }
        else if(plant instanceof Weeds) {
            Weeds wd=(Weeds)plant;
            //TODO do whatever you want to do
        }else if (plant instanceof Fungus) {
            Fungus wd=(Fungus)plant;
            //TODO do whatever you want to do
        }
    }

I hope it help you out. Thanks

Upvotes: 1

Jorn Vernee
Jorn Vernee

Reputation: 33865

A good solution is to use dynamic dispatch. I.e. let the element itself decide what information it wants to print.

class Plant {
    ...
    public String toString() {
        return String.join(" ", getName(), getID(), getColor());
    }
}

class Fungus extends Plant {
    ...
    @Override
    public String toString() {
        return String.join(" ", super.toString(), getPoison());
    }
}

class Flower extends Plant {
    ...
    @Override
    public String toString() {
        return String.join(" ", super.toString(), getSmell(), getThorns());
    }
}

class Weed extends Plant {
    ...
    @Override
    public String toString() {
        return String.join(" ", super.toString(), getPoison(), getEdible(), getMedicinal());
    }
}

Your loop will look like this:

public static void displayPlant(ArrayList<Plant> plantList) {
    for(Plant p : plantList)
        System.out.println(p); // This calls toString
}

Upvotes: 2

Related Questions