Posted by: Arun | October 29, 2008

Instanceof Operator – Possible bad design

Was going through some forum posts, where i came across this interesting topic, which made me think about it. The discussion point was about whether to use ‘instanceof’ operator or not in Java.

Lets come to the point why its not advisable to use it and why your design may need a relook

From Effective C++, by Scott Meyers :

“Anytime you find yourself writing code of the form “if the object is of type T1, then do something, but if it’s of type T2, then do something else,” slap yourself.

Here is an example of the type of abuse Scott Meyers is speaking of :

/**
* Naive, incorrect use of instanceof.
*/
public final class BadInstanceOf {

  public static void doSomething(Animal aAnimal){
    if (aAnimal instanceof Fish){
      Fish fish = (Fish)aAnimal;
      fish.swim();
    }
    else if (aAnimal instanceof Spider){
      Spider spider = (Spider)aAnimal;
      spider.crawl();
    }
  }

  // PRIVATE //
  private static class Animal {}

  private static final class Fish extends Animal {
    void swim(){}
  }
  private static final class Spider extends Animal {
    void crawl(){}
  }
}

The mistake is corrected by using an overridable method :

/**
* Using polymorphism to call different methods.
* Does not use instanceof.
*/
public final class BadInstanceOfFixed {

  public static void main(String... aArgs){
    log("Starting...");
     Animal animal = new Animal();
     doSomething(animal);

     //repoint the same 'animal' reference to other objects :

     animal = new Fish();
     doSomething(animal);

     animal = new Spider();
     doSomething(animal);

     log("Done.");
  }

  /**
  * This method implementation doesn't care at all
  * about Fish/Spider. It just knows that it has
  * been passed an Animal. Different versions of
  * 'move' are called, specific to each Animal.
  */
  public static void doSomething(Animal aAnimal){
    aAnimal.move();
  }

  // PRIVATE //
  private static class Animal {
    void move(){
      log("Move like an animal...");
    }
  }

  private static final class Fish extends Animal {
    void move(){
      log("Move like a fish...");
    }
  }
  private static final class Spider extends Animal {
    void move(){
      log("Move like a spider...");
    }
  }

  private static void log(String aMessage){
    System.out.println(aMessage);
  }
}

An example run of this class :

Starting...
Move like an animal...
Move like a fish...
Move like a spider...
Done.

instanceof operator should only be used as a last resort where there is no other option available with you or only when the solution needs to be patched up and you dont have time to redesign the system again. But always make sure that your next release removes it with a better design. Generally we tend to use it since its easy to use and easy to “visualize”.

Going through the example, its pretty easy to understand and visualize what exactly Scott Meyers is talking about and why he is asking to slap self ;)

So, wherever you have done the mistake, think again and see whether you can have the same problem solved using polymerphic behaviour.


Leave a response

Your response:

Categories