哪一种是更好的Java编程实践:堆叠枚举和枚举构造函数,还是子类化?

哪一种是更好的Java编程实践:堆叠枚举和枚举构造函数,还是子类化?,java,enums,subclassing,multiple-constructors,Java,Enums,Subclassing,Multiple Constructors,给定数量有限且种类不同的项,使用堆叠的枚举和枚举构造函数表示它们,还是对它们进行子类化更好?还是有更好的方法 在我的小RPG程序中(讽刺的是,这个程序应该很简单),一个角色在他的物品清单中有不同种类的物品。项目因其类型、用途和效果而异 例如,清单中的一个项目是一个名为Gremlin的法术卷轴,用于调整实用程序属性。另一件物品可能是一把名为莫特的剑,用于战斗并造成伤害 在我的RPG代码中,我现在尝试了两种表示库存项目的方法。一种方法是子类化(例如,InventoryItem->咒语->调整属性;I

给定数量有限且种类不同的项,使用堆叠的枚举和枚举构造函数表示它们,还是对它们进行子类化更好?还是有更好的方法

在我的小RPG程序中(讽刺的是,这个程序应该很简单),一个角色在他的物品清单中有不同种类的物品。项目因其类型、用途和效果而异

例如,清单中的一个项目是一个名为Gremlin的法术卷轴,用于调整实用程序属性。另一件物品可能是一把名为莫特的剑,用于战斗并造成伤害

在我的RPG代码中,我现在尝试了两种表示库存项目的方法。一种方法是子类化(例如,InventoryItem->咒语->调整属性;InventoryItem->武器->剑)并在需要时实例化每个子类,并指定诸如Gremlin和Mort之类的名称等值

另一种方法是堆叠枚举和枚举构造函数。例如,我为itemCategory、itemSpellTypes和itemWeaponTypes创建了枚举,InventoryItem枚举如下:

public enum InventoryItem {
   GREMLIN(itemType.SPELL, itemSpellTypes.ATTRIBUTE, Attribute.UTILITY),
   MORT(itemType.WEAPON, itemWeaponTypes.SWORD, 30);

   InventoryItem(itemType typeOfItem, itemSpellTypes spellType, Attribute attAdjusted) {
   // snip, enum logic here
   }
   InventoryItem(itemType typeOfItem, itemWeaponTypes weaponType, int dmg) {
   // snip, enum logic here 
   }
   // and so on, for all the permutations of items. 

}

有没有比这两种方法更好的Java编程实践?或者,如果这是唯一的方法,两种方法中哪一种更好?提前感谢您的建议。

如果枚举只包含静态数据,并且逻辑性非常低(最好根本没有逻辑),那么枚举就很好了。如果您的对象根据其种类而具有不同的行为,那么将它们实现为子类通常是一个好主意


正如其他人提到的,您很可能会向对象添加属性,而这些属性对于所有类型都没有意义。颜色属性对武器有意义,但对法术没有意义。在这种情况下,武器和咒语不应该在同一个枚举中。

如果您想向项目添加新属性,可以更容易地将它们作为子类实现。这样,如果一组项获得一个新属性,它将传播到所有子类

例如,如果所有类型的
武器
都被赋予了一定的权重,那么您只需将该属性添加到该类中即可。然后,该属性将传播到子类

对于其他本质上更为静态的事物,因此可以直接指定一个类型,枚举是好的。我在这里自由思考,所以我猜一件
武器
可能会有一个
损伤类型

public abstract class Weapon {

public enum DamageType {

 CUT,
 SMASH,
 PIERCE;
}

private DamageType damageType;

在您描述的上下文中,我将考虑使用类层次结构,而不是EnUM定义,并用接口补充该层次结构;e、 g

/**
 * Root of class hierarchy.
 */
public interface InventoryItem {
}

/**
 * Additional "parallel" interface implemented by some (but not all)
 * InventoryItems and other non-inventory items.
 */
public interface Usable {
  void use();
}

/**
 * A Spell is in InventoryItem and is also Usable.
 */
public abstract class Spell implements InventoryItem, Usable {
}

public class Gremlin extends Spell {
}

/**
 * A Door is *not* an InventoryItem but can be used.
 */
public class Door implements Usable {
}

这种方法的主要优点是,它允许您在不同的上下文中处理给定的对象(作为
InventoryItem
s或可用的
列表)。我要避开枚举的另一个原因是,您可能会定义项目的行为(例如,
spell.cast(Person)
),这在枚举IMHO中不太合适。

+1选择您的答案是因为您的答案的准确性和有用的代码指南。