Java – How to avoid downcasting

javaobject-orientedtype casting

My question is about a special case of the super class Animal.

  1. My Animal can moveForward() and eat().
  2. Seal extends Animal.
  3. Dog extends Animal.
  4. And there's a special creature that also extends Animal called Human.
  5. Human implements also a method speak() (not implemented by Animal).

In an implementation of an abstract method which accepts Animal I would like to use the speak() method. That seems not possible without doing a downcast. Jeremy Miller wrote in his article that a downcast smells.

What would be a solution to avoid downcasting in this situation?

Best Answer

If you have a method that needs to know whether the specific class is of type Human in order to do something, then you are breaking some SOLID principles, particularly :

  • Open/closed principle - if, in the future, you need to add a new animal type that can speak (for example, a parrot), or do something specific for that type, your existing code will have to change
  • Interface segregation principle - it sounds like you are generalizing too much. An animal can cover wide spectrum of species.

In my opinion, if your method expects a particular class type, to call it's particular method, then change that method to accept only that class, and not it's interface.

Something like this :

public void MakeItSpeak( Human obj );

and not like this :

public void SpeakIfHuman( Animal obj );
Related Topic