不能使用具有多态性的instanceof

时间:2015-01-16 16:59:16

标签: java instanceof

编辑:这不是重复,因为我正在解决无法重载类以实现多态的问题。我不是要求比较多态与instanceof。我问一个非常具体的基于场景的问题。

我已经在线阅读了n次,除非我们使用它来实现类的instanceof方法,否则我应该总是尽量避免使用.equals()运算符。< / p>

据说,只要有可能,我们应该尝试实现多态,而不是使用instanceof来确定对象的类型,以决定以下行为。

例如http://www.javapractices.com/topic/TopicAction.do?Id=31

然而,在这个特定情况下,我在super&amp; amp;中没有任何可用的方法。子类(除了toString,equals,accessor和mutator方法)。使用instanceof是否有效?

class Warrior
{

    int damage;
    int defense;
    Item handSlot;

    public Warrior(){
        damage = 0;
        defense = 0;
        handSlot = null;
    }

    private void equipHand(Item item)
    {
        //Determine class of object to decide further actions
        if (item instanceof Weapon){
            this.handSlot= item;
            this.damage += ((Weapon)item).getDamage();  
        }
        else if (item instanceof Shield){
            this.handSlot = item;
            this.defense += ((Shield)item).getProtection();
        }
    }
}


class Item
{
    private String name;
    public Item(String name)
    {
        this.name = name;
    }       
}

class Shield extends Item
{
    private int protection;

    public Shield(String name, int protection){
        super(name);
        this.protection = protection;
    }

    public int getProtection(){
        return protection;
    }
}

class Weapon extends Item
{
    private int damage;

    public Weapon(String name, int damage){
        super(name);
        this.damage = damage;   
    }

    public int getDamage(){
        return damage;
    }   
}

请注意,如果Weapon, Item & Shield class有重载方法(例如:equip()),我可以简单地使用多态。但在这种情况下,装备方法在另一个类中。 在此特定情况下是否可以使用 instanceof 运营商?或者它仍然是一个糟糕的设计?

2 个答案:

答案 0 :(得分:3)

您的设计的替代方法是将equipHand方法从Warrior移至Item(也可以根据此更改它):

/* in Item */
public abstract void giveToWarrior(Warrior w);

/* in Weapon */
@Override
public void giveToWarrior(Warrior w) {
    w.setHandSlot(this);
    w.increaseDamageBy(getDamage());
}

/* in Shield */
@Override
public void giveToWarrior(Warrior w) {
    w.setHandSlot(this);
    w.increaseProtectionBy(getProtection());
}

(我已经使用了Warrior中不存在的一些方法,但是它们的功能应该是不言自明的。进行指示的更改需要实现这些方法。)

此设计解决了当前设计的主要问题,即添加新的Item子类会变得很麻烦,因为这样做也需要更新equipHand

答案 1 :(得分:1)

如您所知ShieldWeapon都延伸Item。因此,最好使用其功能覆盖每个类中的equipHand方法。使用item实例的直接访问方法,而不是使用instance of进行检查。

上述实现的问题,它将为每个类重载额外的方法。

为避免额外的重载方法,请根据要求创建不同的接口。 IWeapon iShield 就像明智一样。在提及界面中定义特定方法。为了更清楚地阅读Head First Design Pattern书的第一章,这将对你有所帮助。