0

I stumbled across that situation but I don't know how to handle it the right way:

class Coffee { }
class CoffeeMix extends Coffee {
  public boolean shaken;
}

I'm saving the coffee items in an array list:

ArrayList<Coffee> coffees = new ArrayList<Coffee>();

So in this array list exist normal coffee objects and coffee mix objects. Now I want to display all coffee mix objects, that are shaken:

for(Coffee c : coffees) {
  //here is the same problem as above
}

As I read in some answers on stackoverflow: instanceof seems to be a bad idea, because it screws the idea behind oo up. So how to handle this?

freakout
  • 53
  • 1
  • 1
  • 11
  • How is this different from [your previous question?](http://stackoverflow.com/q/16658109/139010) – Matt Ball May 20 '13 at 21:23
  • I don't see a problem with using instanceof in this particular case. – Edwin Dalorzo May 20 '13 at 21:23
  • The previous question was crowded with a lot of general blah blah, I thought it would be a better idea to ask a new question straight to the point. – freakout May 20 '13 at 21:25
  • 1
    Read Bill Bill Venners article on [Polymorphism and Interfaces](http://www.artima.com/objectsandjava/webuscript/PolymorphismInterfaces1.html), see the section "When to use instanceof". – Edwin Dalorzo May 20 '13 at 21:30

4 Answers4

0

First of all, when we talk about OO we shouldn't use public fields. I understand why you want to avoid to use instance of. In this case you can use polymorphism and dynamic binding. You can add abstract isShaken method to the base class, make shaken as private at CoffeeMix and override isShaken (return shaken)

michal
  • 1,796
  • 1
  • 13
  • 11
0

You should indeed use polymorphism. That is the best way to go here. But you want you can also use getclass en check if it equals the class that referring to.

docDevil
  • 72
  • 4
  • Instanceof operator has different semantics than comparing classes of the two objects. See http://stackoverflow.com/a/596507/467874 – brabec May 20 '13 at 22:17
  • I did not say that they are the same, but in the situation described above it seems to that it gives him the desired solution and efficient. Don't you agree ? – docDevil May 21 '13 at 20:29
0

You could use the Visitor pattern.

Here's an example how it could be applied to your case:

interface CoffeeElement {
    void accept(CoffeeVisitor visitor);
}

interface CoffeeVisitor {
    void visit(Coffee coffee);
    void visit(CoffeeMix coffee);   
}


class Coffee implements CoffeeElement {

    private final String name;

    public Coffee(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    @Override
    public void accept(CoffeeVisitor visitor) {
        visitor.visit(this);
    }

    @Override
    public String toString() {
        return "Coffee [name=" + getName() + "]";
    }
}

class CoffeeMix extends Coffee {

    public CoffeeMix(String name) {
        super(name);
    }

    @Override
    public void accept(CoffeeVisitor visitor) {
        visitor.visit(this);
    }

    @Override
    public String toString() {
        return "CoffeeMix [name=" + getName() + "]";
    }

}

class PrintingCoffeeVisitor implements CoffeeVisitor {

    @Override
    public void visit(Coffee coffee) {
        // ignore regular coffee
    }

    @Override
    public void visit(CoffeeMix mix) {
        System.out.println(mix);
    }

}

class CoffeeTest {

    public static void main(String[] args) {
        List<Coffee> coffee = new ArrayList<Coffee>();
        coffee.add(new Coffee("Java"));
        coffee.add(new Coffee("Molokai"));
        coffee.add(new CoffeeMix("Season Blend"));

        CoffeeVisitor v = new PrintingCoffeeVisitor();
        for (Coffee c : coffee) {
            c.accept(v);
        }
    }

}

You can also read this explanation of the Visitor pattern. I found it very useful.

https://stackoverflow.com/a/2604798/467874

Community
  • 1
  • 1
brabec
  • 4,632
  • 8
  • 37
  • 63
-2

instanceof seems appropriate here, but if you really don't want to use it, you could try something ugly:

for (Coffee c : coffees) {
    try {
        CoffeeMix blend = (CoffeeMix) c;
        //whatever you want to do with CoffeeMix objects
    } catch (ClassCastException cce) {
        //whatever you want to do with Coffee objects
    }
}

This seems like a situation in which the cure is worse than the disease, but so long as CoffeeMix objects have some fields or properties which are unavailable to Coffee objects, the exception should be thrown, and you will have accomplished your class-wise sorting without having used instanceof at great cost to proper technique.

cabbagery
  • 909
  • 7
  • 16