经常使用instanceof是一种好习惯吗?
场景。 我正在写与游戏相关的代码。 在那个游戏中, Player
(它也是一个类)有一个Item
列表。 还有其他类型的项从Item
inheritance,例如ContainerItem
, DurableItem
或WeaponItem
。
显然,只有List
对我来说非常方便。 但是当我获得玩家物品时,我唯一的方法就是通过使用instanceof
关键字来区分什么类型的物品。 我敢肯定我已经读过,依赖它是不好的做法。
在这种情况下可以使用它吗? 或者我应该重新考虑我的所有结构?
假设我正在编写一些库存代码:
public void showInventory(List- 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- items) { for (Item item : items) { item.show(); } }
我们将所有特定于项的逻辑保留在特定的Item子类中。 这使您的代码库更易于维护和扩展。 它减少了第一个代码样本中每个循环的长期认知压力。 它准备好show()
可以在你还没有设计的地方重复使用。
您应该重新思考并尝试使用多态来实现List
想法。
以下是您的问题的一些参考,可能会有所帮助:
- 优先于实例和向下转换的多态性
- instanceof与getClass in equals方法(采访Josh Bloch)
- 多态性和接口 (请参阅有关何时使用instanceof的部分)
(参考来自Is instanceof被认为是不好的做法?如果是,在什么情况下仍然更可取? )
使用instanceof
恕我直言是一种代码气味。 简单地说 – 它使您的代码程序化,而不是面向对象。 OO方式是使用访问者模式 。
访问者模式还允许您轻松地在其上构建decorator
和chain of responsibility
,从而实现关注点的分离,从而使代码更短,更清晰,更易于阅读和测试。
你真的需要知道确切的课程吗? 你不能利用多态性吗? 毕竟Axe
就像Sword
是Weapon
。
你应该重新考虑你的结构,非元代码中的instanceof
几乎总是反模式的标志。 尝试在Item
-class / interface中定义所有Item
共有的行为(比如有一张图片,一个描述和点击它们时发生的事情),如果适当的话,使用abstract
-keyword,然后使用多态实施细节。
如果你很容易理解它就没关系。
将分支逻辑从它们自然所属的位置移动到子类并不一定是个好主意。 它可能会造成错误的依赖; 它可能会导致臃肿的类,并且可能很难导航和理解。
最后,关于如何在一维空间中物理组织具有多维关注维度的代码。 这不是一个微不足道的问题,它是主观的,并没有灵丹妙药。
特别是,我们的行业inheritance了上个世纪基于那个时代的技术和经济约束而制造的许多规则。 例如,工具非常有限; 程序员非常昂贵; 应用程序发展缓慢。
其中一些规则今天可能不再适用。
我不一定认为instanceof对于知道他们正在做什么的编码员是不利的,并且使用它来避免编写更复杂的代码来绕过它。 一切都有用,也有误用。
话虽如此,您提供的描述不需要instanceof。 有多种方法可以在没有instanceof的情况下实现这一点,而且(最重要的是)备用解决方案必须比使用instanceof更好。 不要只使用非实例解决方案来避免instanceof,因为你听说它很糟糕。
我认为,对于您的场景,非实例解决方案可以使解决方案更易于扩展。
for (Item i: items) { if (ItemTypes.WEAPON_ITEM.equals(i.getType)) { processWeaponType(i); } }
要么
for (Item i: items) { if (WeaponItem.class.equals(i.getType)) { processWeaponType(i); } }
- 检查注释是否属于特定类型
- 如何创建一个我无法更改的类,实现一个接口?
- 在Java中,我可以在instanceof表达式中使用基本类型文字或类型变量吗?
- 如何使用编译时genericsvalidation替换运行时instanceof检查
- Java – 是否有像instanceof这样的“子类”?
- java优化nitpick:在投射之前调用instanceof进行检查是否更快投出一些东西并让它抛出exception?
- “instanceof Void”总是返回false吗?
- 如何实现与hibernate相等而不会失去对称属性的风险?
- 当用于2个不兼容的类时,为什么`instanceof`错误而不是返回`false`?