经常使用instanceof是一种好习惯吗?


问题内容

该方案。我在写与游戏相关的代码。在该游戏中,Player(同时也是一个类)具有的列表Item。有迹象表明,从继承其他类型的项目Item,例如ContainerItemDurableItemWeaponItem

显然,拥有我很方便List<Item>。但是,当我获得玩家物品时,我唯一可以区分哪种物品的方法就是使用instanceof关键字。我确信我已经读过,依赖它是不好的做法。

在这种情况下可以使用吗?还是我应该重新考虑我的所有结构?


问题答案:

假设我正在写一些库存代码:

public void showInventory(List<Item> items) {
    for (Item item : items) {
        if (item instanceof ContainerItem) {
            // container display logic here
        }
        else if (item instanceof WeaponItem) {
            // weapon display logic here
        }
        // etc etc
    }
}

这样可以编译并正常工作。但是它错过了面向对象设计的关键思想: 您可以定义父类来做一般有用的事情,而让子类填充特定的重要细节。

以上的替代方法:

abstract class Item {
    // insert methods that act exactly the same for all items here

    // now define one that subclasses must fill in themselves
    public abstract void show()
}
class ContainerItem extends Item {
    @Override public void show() {
        // container display logic here instead
    }
}
class WeaponItem extends Item {
    @Override public void show() {
        // weapon display logic here instead
    }
}

现在show(),在所有清单显示逻辑的子类中,方法都有一个地方可以看。我们如何访问它?简单!

public void showInventory(List<Item> items) {
    for (Item item : items) {
        item.show();
    }
}

我们将所有特定于项目的逻辑保留在特定的Item子类中。这使您的代码库更易于维护和扩展。它减少了第一个代码样本中长for-
each循环的认知压力。它show()可以在您尚未设计的地方重复使用。