Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java - A smarter way to determine the child class?

I need an intelligent way to differentiate between multiple objects, all child classes from the same parent class. Consider this parent class and two child classes:

public class Fruit {
    String name;
    public Fruit(String a){
        this.name = a;
    }
}
public class Orange extends Fruit {
    public Orange(String a){
        super(a);
    }
}
public class Apple extends Fruit {
    int price;
    public Apple(String a, int b){
        super(a);
        this.price = b;
    }
    public void checkPrice(){
        if(this.price>2)
            System.out.print("  --  This apple is too expensive!");
        else
            System.out.print("  --  This apple is cheap.");
    }
}

(Also suppose I have a lot more Fruit child classes, not shown here.) Now I want to store all the Fruit in a Fruit Cart:

public class FruitCart {
    Fruit[] cart;
    public FruitCart(){
        cart = new Fruit[4];
        cart[0] = new Apple("Apple #1", 1);
        cart[1] = new Orange("Orange #1");
        cart[2] = new Apple("Apple #2", 3);
        cart[3] = new Apple("Apple #3", 2);
    }
    public void cartInventory(){
        for(int i=0; i<cart.length; i++){
            System.out.print("Item "+i+")  "+cart[i].getClass());
            if(cart[i].getClass().getName().equals("area.Apple")){
                Apple tmp = (Apple)cart[i];
                tmp.checkPrice();
            }
            System.out.println();
        }
    }
}

The cartInventory() method looks for Apple objects and then runs a method specific to Apples. I'll get back to that "how do I recognize an Apple" part in a second, but first, I run the whole program out of main():

public class MainEvent {
    public static void main(String[] args){
        FruitCart cart = new FruitCart();
        cart.cartInventory();
        System.out.println("END OF PROGRAM.");
    }
}

BTW, Output is:

Item 0)  class area.Apple  --  This apple is cheap.
Item 1)  class area.Orange
Item 2)  class area.Apple  --  This apple is too expensive!
Item 3)  class area.Apple  --  This apple is cheap.
END OF PROGRAM.

So the whole thing works fine... but I'm bothered by the mechanism which inspects the Fruit objects and determines if the Fruit is an Apple. The way I do it is pretty clumsy:

if(cart[i].getClass().getName().equals("area.Apple"))

Basically, I call getName() and do a String comparison to see if cart[i] is an Apple or not. Isn't there a smarter way to do this? I keep thinking there must be a way to use cart[i].getClass() somehow... but I don't see a smarter way. Isn't there some way to take advantage of the parent/child relationship between Fruit & Apple?

Any suggestions? Thanks!

like image 972
Pete Avatar asked Jan 06 '17 21:01

Pete


2 Answers

You could put the method checkPrice in your Fruit class and eventually every child could override it.

public class Fruit {
    String name;
    public Fruit(String a){
        this.name = a;
    }

    // just a default implementation that does nothing
    // (or does whatever you want)
    public void checkPrice(){}

}

Now cartInventory would look like this:

public void cartInventory(){
    for(int i=0; i<cart.length; i++){
        System.out.print("Item "+i+")  "+cart[i].getClass());
        cart[i].checkPrice();
        System.out.println();
    }
}
like image 68
Loris Securo Avatar answered Sep 29 '22 19:09

Loris Securo


I suppose you can check with instanceOf. Eg :

if(cart[i] instanceOf Apple){
// do something
} else if(cart[i] instanceOf Orange){
//do something
}

However in practice it should not be used as its against the OOPS concept.

like image 40
vk3105 Avatar answered Sep 29 '22 21:09

vk3105