Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Avoding instanceof in Java

Tags:

In my application I have a 2d array of entities to represent a grid. Each location in the grid can either be empty or occupied by an entity (in this case it's just a person or wall). Right now I use instanceof to check whether an entity is a person or a wall.

I was thinking of giving each entity a method which returns an enum stating their type so i.e. a wall entity would return EntityType.WALL. I was wondering if this is the best idea to remove the use of instanceof or is instanceof suitable in this scenario?

like image 345
John Radke Avatar asked Nov 22 '15 23:11

John Radke


People also ask

What can I use instead of Instanceof in Java?

Having a chain of "instanceof" operations is considered a "code smell". The standard answer is "use polymorphism".

Is Instanceof a code smell?

Probably most of you have already heard that using “instanceof” is a code smell and it is considered as a bad practice. While there is nothing wrong in it and may be required at certain times, but the good design would avoid having to use this keyword.

Is Instanceof an Antipattern?

You can avoid the need of using instanceof if Item defines an abstract method, forcing each subclass to implement its own. Probably rethink your structure. The pattern you are describing is really an anti-pattern. Yes, in general using `instanceof`` is a symptom of a bad/poor design.

What is the difference between Instanceof and isInstance?

The instanceof operator and isInstance() method both are used for checking the class of the object. But the main difference comes when we want to check the class of objects dynamically then isInstance() method will work. There is no way we can do this by instanceof operator.


1 Answers

Use Tell, Don't Ask: instead of asking the objects what they are and then reacting on that, tell the object what to do and then walls or people do decide how they do what they need to do.

For example:

Instead of having something like this:

public class Wall {     // ... }  public class Person {     // ... }  // later public class moveTo(Position pos) {     Object whatIsThere = pos.whatIsThere();     if (whatIsThere instanceof Wall) {          System.err.println("You cannot move into a wall");     }     else if (whatIsThere instanceof Person) {          System.err.println("You bump into " + person.getName());     }     // many more else branches... } 

do something like this:

public interface DungeonFeature {     void moveInto(); }  public class Wall implements DungeonFeature {     @Override     public void moveInto() {         System.err.println("You bump into a wall");     }     // ... }  public class Person implements DungeonFeature {     private String name;      @Override     public void moveInto() {         System.err.println("You bump into " + name);     }      // ... }  // and later public void moveTo(Position pos) {     DungeonFeature df = currentPosition();     df.moveTo(pos); } 

This has some advantages.

First, you don't need to adjust a giant if then else tree each time you add a new dungeon feature.

Second, the code in the dungeon features is self-contained, the logic is all in the said object. You can easily test it and move it.

like image 142
Robert Avatar answered Nov 09 '22 00:11

Robert