我几天前做了similar question,但现在我有了新的要求,新的挑战=)。像往常一样,一旦我不想解释特定领域的东西,我就会将动物枚举用于教学目的
我有一个动物的基本枚举,整个动物园都使用它(我可以添加东西,但必须保持兼容性):
public enum Animal {
DOG,
ELEPHANT,
WHALE,
SHRIMP,
BIRD,
GIRAFFE;
}
我需要将它们分类为几个非相关的类别,如灰色动物(鲸鱼(我的鲸鱼是灰色的)和大象),小动物(鸟,虾和狗),海洋动物(鲸鱼和虾)。
我可以像我之前的问题中所建议的那样添加很多布尔值,比如isGray,isSmall和isFromSea,但是我想要一种可以将其保存在其他地方的方法(所以我的枚举不需要知道许多)。类似的东西:
public enum Animal {
DOG,
ELEPHANT,
WHALE,
SHRIMP,
BIRD,
GIRAFFE;
public boolean isGray() {
// What comes here?
}
}
其他地方
public enum GrayAnimal {
WHALE,
ELEPHANT;
}
这怎么可能?我是否要求Java过多?
答案 0 :(得分:8)
您可以创建方法
Set<Animal> grayAnimals(){
return EnumSet.of(Animal.WHALE, Animal.ELEPHANT);
}
答案 1 :(得分:2)
我认为最好将这些属性存储在枚举实例中,即
public enum Animal {
DOG(NOT_GRAY),
ELEPHANT(GRAY),
WHALE(GRAY),
SHRIMP(NOT_GRAY),
BIRD(NOT_GRAY),
GIRAFFE(NOT_GRAY);
private static boolean GRAY = true;
private static boolean NOT_GRAY = !GRAY;
private Animal(boolean isGray) {
// snip
}
}
你甚至可以将几个布尔属性编码为一个字节(或者改为使用BitSet);
public enum Animal {
DOG(),
ELEPHANT(GRAY | BIG),
WHALE(GRAY | BIG),
SHRIMP(),
BIRD(),
GIRAFFE(BIG);
private static byte GRAY = 0x01;
private static byte BIG = GRAY << 1;
private final byte _value;
private Animal() {
this(0x00);
}
private Animal(byte value) {
_value = value;
}
public boolean isGray() {
return _value & GRAY != 0x00;
}
public boolean isBig() {
return _value & BIG != 0x00;
}
}
然而,简单地这样做是什么:
public class GrayAnimal {
public static final Animal ELEPHANT = Animal.ELEPHANT;
public static final Animal WHALE = Animal.WHALE;
}
或类似的东西
public enum Animal {
DOG,
ELEPHANT,
WHALE,
SHRIMP,
BIRD,
GIRAFFE;
// thanks to Mihir, I would have used a regular HashSet instead
public static final Set<Animal> GRAY = Collections.unmodifiableSet(EnumSet.of(ELEPHANT, WHALE));
}
答案 2 :(得分:1)
请记住,枚举仅在您需要区分代码中的对象时才有用 - 除了可以作为代码输入外,它们没用。
这是相关的,因为您在软件中引入元素,从长远来看,这些元素会变成糟糕的代码味道。
例如,除了语句之外,你如何使用这些:
if(critter.type == WHALE)
critter.movement=WATER;
else if(critter.type == ELEPHANT)
这应该立即警告任何OO程序员 - 开关是一个糟糕的代码气味,因为他们几乎总是指示不良的OO设计。)
另一种方法是创建一组有限的对象,由数据初始化,最好不是代码。
你可能有一个具有鲸鱼属性的生物实例 - 也许whale.move()将使用WaterMovement的实例,而大象包含并使用LandMovement的实例。
通常,在OO中编程而不是使用开关和枚举将会破坏大量代码。
每次编写方法时,请记住“不要向对象询问数据,然后对对象进行操作,而是要求对象为您执行操作”这句咒语。
答案 3 :(得分:0)
我不知道为什么你想把它放在另一个枚举中,当你把它放在那个函数中时:
public boolean isGray() {
return this == WHALE || this == ELEPHANT;
}
答案 4 :(得分:0)
可能是这样的:
package p;
import java.util.*;
enum Type {
small,big,grey;
}
enum Animal {
bird(EnumSet.of(Type.small)),whale(EnumSet.of(Type.big, Type.grey)),elephant(EnumSet.of(Type.big, Type.grey));
Animal(final EnumSet<Type> types) { this.types=types; }
EnumSet<Type> types=EnumSet.noneOf(Type.class);
boolean is(final Type type) { return types!=null?types.contains(type):false; }
public static void main(String[] arguments) {
for(Animal a:values()) {
System.out.println(a+" "+a.types);
}
}
}
答案 5 :(得分:0)
我认为最好不要通过这种分类来污染你的枚举。最好将类别与枚举分离,以便以后可以添加更多类别,而不会影响枚举。这是对课堂设计的关注点和单一责任原则的分离。
为此,只需使用EnumSet来保存实例,即:
public enum Animal {
DOG,
ELEPHANT,
WHALE,
SHRIMP,
BIRD,
GIRAFFE;
}
public static final EnumSet<Animal> GRAY_ANIMALS = EnumSet.of(ELEPHANT, WHALE);
如果你想在简单成员资格之上添加功能,或者你想要更多的语法糖扩展EnumSet
public class GrayAnimals extends EnumSet<Animal> {
public static final GrayAnimals INSTANCE = new GrayAnimals(ELEPHANT, WHALE);
private GrayAnimals(Animal...animals) {
Collections.addAll(this, animals);
}
public boolean isGray(Animal animal) { return contains(animal); }
// ... other methods
}