简体   繁体   English

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

[英]Which is better Java programming practice: stacking enums and enum constructors, or subclassing?

Given a finite number of items which differ in kind, is it better to represent them with stacked enums and enum constructors, or to subclass them? 给定有限种类的项目,是否最好用堆叠的枚举和枚举构造器来表示它们,或者将它们子类化? Or is there a better approach altogether? 还是完全有更好的方法?

To give you some context, in my small RPG program (which ironically is supposed to be simple), a character has different kinds of items in his or her inventory. 为了给您一些背景信息,在我的小型RPG程序中(讽刺的是,它很简单),角色的库存中有不同种类的物品。 Items differ based on their type and use and effect. 物品因其类型,用途和效果而异。

For example, one item of inventory is a spell scroll called Gremlin that adjusts the Utility attribute. 例如,清单中的一项是名为Gremlin的咒语滚动,可调整Utility属性。 Another item might be a sword called Mort that is used in combat and inflicts damage. 另一个物品可能是称为Mort的剑,用于战斗并造成伤害。

In my RPG code, I now have tried two ways of representing inventory items. 在我的RPG代码中,我现在尝试了两种表示库存物料的方法。 One way was subclassing (for example, InventoryItem -> Spell -> AdjustingAttributes; InventoryItem -> Weapon -> Sword) and instantiating each subclass when needed, and assigning values such as names like Gremlin and Mort. 一种方法是子类化(例如,InventoryItem-> Spell-> AdjustingAttributes; InventoryItem-> Weapon-> Sword),并在需要时实例化每个子类,并分配诸如Gremlin和Mort之类的值。

The other way was by stacking enums and enum constructors. 另一种方法是通过堆叠枚举和枚举构造函数。 For example, I created enums for itemCategory and itemSpellTypes and itemWeaponTypes, and the InventoryItem enum was like this: 例如,我为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. 

}

Is there a better Java programming practice than these two approaches? 是否有比这两种方法更好的Java编程实践? Or if these are the only ways, which of the two is better? 或者,如果只有这些方法,那么哪种更好? Thanks in advance for your suggestions. 预先感谢您的建议。

Enums are good if the only hold static data and very minimal logical (preferably no logic at all). 如果枚举仅包含静态数据且逻辑最少(最好根本没有逻辑),则枚举会很好。 If your objects are meant to have different behaviors depending on their kind, it's usually a good idea to implement them as subclasses. 如果您的对象根据其种类而具有不同的行为,通常最好将它们实现为子类。

As others mentioned, you're very likely to add attributes to your objects and these attributes won't make sense for all kinds. 正如其他人提到的那样,您很有可能向对象添加属性,而这些属性对所有类型都没有意义。 Eg. 例如。 a color attribute makes sense for a weapon but not for a spell. 颜色属性对武器有意义但对咒语没有意义。 In that case weapon and spell should not be in the same enum. 在这种情况下,武器和咒语不应位于同一枚举中。

If you want to add new attributes to the items it could be easier to implement them as subclasses. 如果要向项目添加新属性,将它们实现为子类可能会更容易。 In this way, if a group of items gets a new attribute it will propagate to all subclasses. 这样,如果一组项目获得新属性,它将传播到所有子类。

For instance, if all kinds of Weapon gets a certain weight assigned to it, you simply add that attribute to that class. 例如,如果各种Weapon都分配了一定的权重,则只需将该属性添加到该类中即可。 This attribute will then propagate to subclasses. 然后,此属性将传播到子类。

Regarding other things that are more static in nature, and thus can directly be assigned a type, enums are good. 对于本质上是静态的,因此可以直接分配类型的其他事物,枚举是好的。 I'm thinking freely here, so I guess a Weapon could have a DamageType assigned to it: 我在这里自由思考,所以我想Weapon可能会分配一个DamageType

public abstract class Weapon {

public enum DamageType {

 CUT,
 SMASH,
 PIERCE;
}

private DamageType damageType;

In the context you describe I would consider using a class hierarchy as opposed to enum definitions and supplementing this hierarchy with interfaces; 在上下文中,我将考虑使用类层次结构而不是枚举定义,并使用接口来补充该层次结构。 eg 例如

/**
 * 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 {
}

The main advantage of this approach is that it allows you to treat a given object in different contexts (as InventoryItem s or as a list of Usable s). 这种方法的主要优点是,它允许您在不同的上下文中对待给定的对象(作为InventoryItemUsable的列表)。 The other reason I would steer clear away from enums is that you're likely to define behaviour on your items (eg spell.cast(Person) ) and this doesn't sit well in enums IMHO. 我要避免使用枚举的另一个原因是,您可能会定义项目的行为(例如spell.cast(Person) ),而这在枚举IMHO中并不理想。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM