Onur Arı
Onur Arı

Reputation: 512

How can I avoid instanceof when function behavior depends on type?

I am designing a basic game engine. I have an abstract GameObject class which are inherited by two classes Player and Bullet. I am trying to handle collision of two game objects. If both of the collided objects are the same, nothing happens. If one of them is bullet and other is player, the player's health is set to 0. Here is a snippet showing the required method and class definitions:

public interface GameObject {
    void onCollision(GameObject gameObject);
}

public class GameObjectImpl implements GameObject {
    ...
    // By default, do nothing.
    @Override
    public void onCollision(GameObject object) {}    
}


public class Player extends GameObjectImpl {
   ...
   @Override
   public void onCollision(GameObject gameObject) {
      if (gameObject instanceof Player) {
          // Do nothing
      } else if (gameObject instanceof Bullet) {
          this.health = 0;
      }
   }
}

I want to avoid instanceof but I could not think of any way to do so. I wanted to implement it with using polymorphism as clients of GameObject interface should not know the details about bullets or players etc. It will just call onCollision method for objects in each frame. How can I achieve this with a cleaner code? Thank you.

Upvotes: 1

Views: 169

Answers (1)

Smutje
Smutje

Reputation: 18143

It might look cumbersome because Javas mechanism of resolving target methods is not the best, but you can try something similar to

public class Player extends GameObjectImpl {
   ...
    @Override
    public void onCollision(GameObject gameObject) {
        gameObject.collideWith(this);
    }
}

and then extend the GameObject with the appropriate "callback":

public interface GameObject {
    void onCollision(GameObject gameObject);
    void collideWith(Player player);
}

and then

public class Player extends GameObjectImpl {
   ...
    @Override
    public void onCollision(GameObject gameObject) {
        gameObject.collideWith(this);
    }

    @Override
    public void collideWith(Player player) {
        // ... do nothing, shouldn't happen
    }
}

and

public class Bullet extends GameObjectImpl {
   ...
    @Override
    public void onCollision(GameObject gameObject) {
        gameObject.collideWith(this);
    }

    @Override
    public void collideWith(Player player) {
        player.setHealth(0);
    }
}

For further reading you might search for the Visitor pattern in Java.

Upvotes: 1

Related Questions