对于现实生活中的设备,我具有以下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);
}
}
这种方法仍然没有继承或更多的进化类型,我想最好避免使用枚举,这是更好的选择。