对于现实生活中的设备,我具有以下Enum常数:

HELMET,
CHESTPIECE,
BOOTS,
SWORD,
MACE,
HAMMER,
SHIELD,
BOW,
CROSSBOW,
STAFF
...;


我还有一个叫做Battle的类,它指示在特定的战斗中可以使用什么设备。例如:

new Battle(Equipment.HAMMER, Equipment.SHIELD, EQUIPMENT.BOW);

这意味着只能使用锤子,盾牌或弓箭。

现在,我对此进行了扩展,并需要子类别。例如:

new Battle(Equipment.SHIELD, Equipment.Weapons.values())

这相当于说:

new Battle(Equipment.SHIELD, Equipment.SWORD, Equipment.MACE, Equipment.HAMMER, ...)

这也意味着new Battle(Equipment.values())应该产生每个枚举值

由于Enum是最终版本,因此我尝试了以下操作:

public interface Equipment { }

public enum MeleeWeapon implements Equipment
{
    SWORD,
    MACE,
    HAMMER,
    STAFF, ...;
}

public enum RangedWeapon implements Equipment
{
    BOW, CROSSBOW;
}

...


但是与此同时,我无法说Equipment.Weapon.values() // get all weapons, ranged and melee。类之间没有继承关系的感觉,我也失去了接口中未定义的所有内容。这里感觉不是一个好的解决方案。

我尝试过常规课程:

public abstract class Equipment
{
    private static Set<Equipment> instances = new HashSet<>();

    public static Set<Equipment> values()
    {
        return instances;
    }

    public Equipment()
    {
        instances.add(this);
    }
}

public abstract class Weapon extends Equipment
{
    private static Set<Weapon> instances = new HashSet<>();

    public static Set<Weapon> values()
    {
        return instances;
    }

    public Weapon()
    {
        super() // explicit call
        instances.add(this);
    }
}

public class MeleeWeapon extends Weapon
{
    private static Set<MeleeWeapon> instances = new HashSet<>();

    public static final MeleeWeapon SWORD = new MeleeWeapon();
    public static final MeleeWeapon MACE = new MeleeWeapon();
    ...

    public static Set<MeleeWeapon> values()
    {
        return instances;
    }

    public MeleeWeapon()
    {
        super() // explicit call
        instances.add(this);
    }
}


不幸的是,有大量重复的代码,占用大量内存,并且public static Set<Weapon> values()还会导致编译错误,因为它试图用不同的返回类型覆盖超类中的values()。我能够使用泛型(<? extends Weapon>)解决此问题,但这仍然是一个糟糕的解决方案。

这里正确的方法是什么?我需要使用枚举值进行继承,但是我找不到方法。

最佳答案

仍然保持枚举用法,可以将枚举的每个元素与其所属的组相关联,然后在专用方法中返回经过过滤的元素组。

我们将需要另一个较小的枚举,该枚举枚举要过滤的属性,例如:

public enum EquipmentType {

  WEAPON, ARMOR, TOOL, CLOTHING;

}


枚举的元素与它们各自的组相关联:

public enum Equipment {

  HELMET(ARMOR),
  CHESTPIECE(ARMOR),
  BOOTS(ARMOR, CLOTHING),
  SWORD(WEAPON),
  MACE(WEAPON),
  HAMMER(WEAPON, TOOL),
  SHIELD(ARMOR),
  BOW(WEAPON),
  CROSSBOW(WEAPON),
  STAFF(WEAPON);

  private final Set<EquipmentType> types;

  Equipment(EquipmentType... eqTypes) {
    this.types = Arrays.stream(eqTypes)
                       .collect(Collectors.toSet());
  }

  // common filtering method
  private static List<Equipment> filterByType(EquipmentType type) {
    return Arrays.stream(values())
        .filter(eq -> eq.types.contains(type))
        .collect(Collectors.toList());
  }

  // dedicated methods for each group of items
  public static List<Equipment> getWeapons() {
    return filterByType(WEAPON);
  }

  public static List<Equipment> getArmor() {
    return filterByType(ARMOR);
  }

}


这种方法仍然没有继承或更多的进化类型,我想最好避免使用枚举,这是更好的选择。

10-08 08:46