Henry Maathuis
Henry Maathuis

Reputation: 123

Avoiding instanceof Java

I am trying to find a way to bypass the use of instanceof. I've created a class Item which has multiple subclasses like WeaponItem and BodyItem. Now I would like to make to do a call such as equip(Item) and it should determine by itself which overloaded function it should call such as equip(BodyItem).

Is there a way to bypass the use of instanceof for this case and what would you recommend? I've heard that in most cases using instanceof is bad practice and therefor I want to know what the alternatives are.

Code:

inv.equip(it); // inv = inventory object, it = Item

An example of equip function within inventory class how I preferably want it

public void equip(HelmItem it) 
{
    if (it != this.getHelm())
    {
        this.setHelm(it);
    }
}

How I had it before:

public void equip(Item it)
{
    if (it instanceof WeaponItem)
    {
        if (it != this.getWeapon())
        {
            this.setWeapon((WeaponItem) it);
        } 
    } etc for all subclasses of item
}

Upvotes: 0

Views: 495

Answers (2)

Dragan Bozanovic
Dragan Bozanovic

Reputation: 23552

Indeed, this could be solved with a visitor pattern.

However, it does not have to be a full-blown visitor, but a simplified variation of it. You could pass the inventory to the item and let the item do whatever it wants with it:

abstract class Item {
    public abstract void equip(Inventory inv);
}

class HelmItem extends Item {
    @Override
    public void equip(Inventory inv) {
        inv.setHelm(this);
    }
}

class WeaponItem extends Item {
    @Override
    public void equip(Inventory inv) {
        inv.setWeapon(this);
    }
}

Then you can just call:

it.equip(inv)

without the instanceof operator.

Upvotes: 4

christopher
christopher

Reputation: 27346

Why not put the method in the Item concrete class, and it can equip itself? It's a little counter intuitive but it would solve your problem.

public class SomeConcreteItem extends Item {
    public void equip(Body body) {
        // Just an example.
        body.getSections().get(0).equip(this);
    }
}

That way, the concrete implementation knows how to equip itself and the classes that use it don't care. You can reference it by the Item superclass and provided that the Item superclass has an abstract method public void equip(Body body);, then you don't ever need to know about the concrete implementation and, therefore, no need for the instanceof operator.

A Note on Introducing a Design Pattern

You should be careful about introducing Design Patterns. People have a bad habit of leaping straight to a complicated pattern to solve a problem, when really something simpler and (in my opinion) more elegant is available.

Upvotes: 2

Related Questions