我刚刚发现Java允许枚举实现接口。它的一个好的用例是什么?
当前回答
枚举不只是表示被动的集合(例如颜色)。它们可以表示具有功能的更复杂的对象,因此你可能想要在这些对象上添加更多的功能——例如,你可能有诸如Printable、Reportable等接口,以及支持这些接口的组件。
其他回答
另一个可能性:
public enum ConditionsToBeSatisfied implements Predicate<Number> {
IS_NOT_NULL(Objects::nonNull, "Item is null"),
IS_NOT_AN_INTEGER(item -> item instanceof Integer, "Item is not an integer"),
IS_POSITIVE(item -> item instanceof Integer && (Integer) item > 0, "Item is negative");
private final Predicate<Number> predicate;
private final String notSatisfiedLogMessage;
ConditionsToBeSatisfied(final Predicate<Number> predicate, final String notSatisfiedLogMessage) {
this.predicate = predicate;
this.notSatisfiedLogMessage = notSatisfiedLogMessage;
}
@Override
public boolean test(final Number item) {
final boolean isNotValid = predicate.negate().test(item);
if (isNotValid) {
log.warn("Invalid {}. Cause: {}", item, notSatisfiedLogMessage);
}
return predicate.test(item);
}
}
和使用:
Predicate<Number> p = IS_NOT_NULL.and(IS_NOT_AN_INTEGER).and(IS_POSITIVE);
它是可扩展性所必需的——如果有人使用您开发的API,则您定义的枚举是静态的;它们不能被添加或修改。但是,如果让它实现一个接口,使用API的人可以使用相同的接口开发自己的枚举。然后,您可以向枚举管理器注册这个枚举,枚举管理器将枚举与标准接口结合在一起。
Edit: @Helper方法有一个完美的例子。考虑让其他库定义新的操作符,然后告诉管理器类“嘿,这个枚举存在——注册它”。否则,您只能在自己的代码中定义操作符——就没有可扩展性了。
枚举就像Java类,它们可以有构造函数、方法等。唯一不能使用它们的是new EnumName()。实例是在枚举声明中预定义的。
枚举只是伪装的类,所以在大多数情况下,可以用类做的任何事情都可以用枚举做。
我想不出一个理由,enum不应该能够实现接口,同时我也想不出一个好的理由。
我想说的是,一旦你开始往枚举中添加接口或方法,你应该考虑把它变成一个类。当然,我确信有一些案例可以用于执行非传统枚举内容,而且由于限制是人为的,所以我赞成让人们在枚举中做他们想做的事情。
对我来说,使用枚举接口的最佳用例之一是谓词过滤器。这是一种非常优雅的方法来弥补apache集合的类型化不足(如果不能使用其他库)。
import java.util.ArrayList;
import java.util.Collection;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.Predicate;
public class Test {
public final static String DEFAULT_COMPONENT = "Default";
enum FilterTest implements Predicate {
Active(false) {
@Override
boolean eval(Test test) {
return test.active;
}
},
DefaultComponent(true) {
@Override
boolean eval(Test test) {
return DEFAULT_COMPONENT.equals(test.component);
}
}
;
private boolean defaultValue;
private FilterTest(boolean defautValue) {
this.defaultValue = defautValue;
}
abstract boolean eval(Test test);
public boolean evaluate(Object o) {
if (o instanceof Test) {
return eval((Test)o);
}
return defaultValue;
}
}
private boolean active = true;
private String component = DEFAULT_COMPONENT;
public static void main(String[] args) {
Collection<Test> tests = new ArrayList<Test>();
tests.add(new Test());
CollectionUtils.filter(tests, FilterTest.Active);
}
}
推荐文章
- 在流中使用Java 8 foreach循环移动到下一项
- 访问限制:'Application'类型不是API(必需库rt.jar的限制)
- 用Java计算两个日期之间的天数
- 如何配置slf4j-simple
- 在Jar文件中运行类
- 带参数的可运行?
- 我如何得到一个字符串的前n个字符而不检查大小或出界?
- 我可以在Java中设置enum起始值吗?
- Java中的回调函数
- c#和Java中的泛型有什么不同?和模板在c++ ?
- 在Java中,流相对于循环的优势是什么?
- Jersey在未找到InjectionManagerFactory时停止工作
- 在Java流是peek真的只是调试?
- Recyclerview不调用onCreateViewHolder
- 将JSON字符串转换为HashMap