0

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
}
3
  • 2
    Look up double-dispatch and the visitor pattern Commented Jun 20, 2015 at 11:46
  • possible duplicate of avoid instanceof in Java Commented Jun 20, 2015 at 11:48
  • 1
    Can you share the code you are trying ? Commented Jun 20, 2015 at 11:51

2 Answers 2

4

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.

Sign up to request clarification or add additional context in comments.

3 Comments

This solved by problem indeed! Thanks for sharing your thoughts! It still remains fairly counter-intuitive as the semantics say that an item equips the inventory, but it works as a solution so thanks! :D
Yes, that could be overcome by preserving the inv.equip(it) method, but in the implementation of it you can invoke it.equip(this). This way you have a centralized place for adding items to the inventory, which is good because it adheres to DRY, and you can do something else there as well, like counting the items added, checking if the inventory is full etc.
While we said similar things, you did a better job and provided a complete example. +1
2

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.