【发布时间】:2011-01-05 14:12:16
【问题描述】:
有没有一种简单的方法来继承 Java enum?
我问这个是因为我喜欢其中的 10 个实现相同的接口,但它们对某些方法也有相同的实现,所以我想通过将所有相同的实现放在扩展 Enum 的中间对象中来重用代码它也是我需要的所有其他人的超类。
也许没有我想的那么简单?
提前致谢
【问题讨论】:
标签: java inheritance enums
有没有一种简单的方法来继承 Java enum?
我问这个是因为我喜欢其中的 10 个实现相同的接口,但它们对某些方法也有相同的实现,所以我想通过将所有相同的实现放在扩展 Enum 的中间对象中来重用代码它也是我需要的所有其他人的超类。
也许没有我想的那么简单?
提前致谢
【问题讨论】:
标签: java inheritance enums
你不能这样做,因为语言不允许你这样做。并且出于一个很好的逻辑原因:仅当您可以从子类中删除一些枚举值而不是添加新的枚举值时,对枚举进行子类化才有意义。否则你会破坏Liskov Substitution Principle。
简而言之,只要期望超类的实例,子类的每个实例都应该是可以接受的。如果你在枚举子类中添加一个新的枚举成员,那显然不能被只知道超级枚举的人接受。
有关更多详细信息和可能的替代方案,请参阅this earlier answer of mine。
在您的具体情况下,@Jason 的建议可能会提供一个很好的解决方案(为他 +1 :-)
好点,我在上面有点草率 :-) 在实施方面你是对的。但是,从逻辑的角度来看,枚举类型完全由其有效值的集合来描述。通常,适当的子类是其超类的特化。换句话说,有效的子类实例集(应该)始终是超类实例集的子集。 (每只狗都是动物,但不是每只动物都是狗。)
【讨论】:
enum E { INSTANCE {} }。 E.INSTANCE.getClass() == E.class 将评估为假。 (但我意识到这通常没有什么帮助。)
我问这个是因为我喜欢其中的 10 个实现相同的接口,但它们对某些方法也有相同的实现,所以我想通过将所有相同的实现放在扩展 Enum 的中间对象中来重用代码也是我需要的所有其他人的超类。
使用静态帮助类怎么样?
interface Animal
{
public void speak();
}
class AnimalHelper
{
public static void speakHelper(Animal animal) {
// common methods here
}
}
enum Dog implements Animal { SCHNAUZER, LABRADOR, ST_BERNARD, DACHSHUND;
@Override public void speak() {
AnimalHelper.speakHelper(this);
}
};
enum Bird implements Animal { OWL, FINCH, DUCK, GOOSE; }
@Override public void speak() {
AnimalHelper.speakHelper(this);
}
};
【讨论】:
使用 Java 8,您可以使用 default methods 将共享实现放入接口中。
public class DefaultMethodOnEnumInterface {
public interface Greeter {
default public void greet() {
System.out.println("Hello, world!");
}
}
public enum Greeters implements Greeter {
A,
B;
}
public static void main(String[] args) {
Greeters.A.greet();
Greeters.B.greet();
}
}
如果需要访问Enum类实现的方法,则在接口中添加签名:
public interface Greeter {
default public void greet() {
System.out.println("Hello, world! This is " + name());
}
/**
* @see Enum#name()
*/
public String name(); // implemented by Enum
}
【讨论】:
尝试使用 Apache commons 包中的 Enums,您可以在其中子类化 Enums。 不知道对你有没有帮助。
【讨论】:
虽然在 Java 中有 proposals for abstract enums,但其收益被认为太低而无法超过成本。你必须坚持转发方法调用。
【讨论】:
该语言不允许您这样做,因为枚举旨在有效地表示枚举值,而不是用于实现代码。尝试使用另一种模式,例如静态帮助程序(实用程序)类。
【讨论】:
@Jason S 给出了很好的回复,但是静态方法让你失去了 OOP 的潜力。
委托呢?我的意思是:
定义一个通用接口“I_A”,您可以在其中定义所有 getter/setter 和所有其他方法。
定义一个“struct-like”类“S_C”:它只实现getter和setter,其他方法都是空的,因为没用。
您的所有枚举都实现了“I_A_Delegating”并具有“S_C”的本地实例
代码示例:
public class EnumFakeExtension{
/**"I_A"*/
public static interface CommonInterface{
public Object getFieldOne();
public Object getFieldTwo();
public void setFieldOne(Object o);
public void setFieldTwo(Object o);
public void someMethod();
}
/*"S_C"*/
public static class CommonDelegator_FieldKeeper implements CommonInterface{
Object oOne, oTwo;
public Object getFieldOne(){ return oOne; }
public Object getFieldTwo(){ return oTwo; }
public void setFieldOne(Object o){ oOne = o; }
public void setFieldTwo(Object o){ oTwo = o; }
public void someMethod(){ /*empty*/ }
}
/**"I_A_Delegating"*/
public static interface CommonInterface_Delegating extends CommonInterface{
public CommonInterface getDelegate();
public void setDelegate(CommonInterface delegator);
/**Just to simplify*/
public default void setDefaultDelegate(CommonInterface delegator){
setDelegate( new CommonDelegator_FieldKeeper() );
}
public default Object getFieldOne(){ return getDelegate().getFieldOne(); }
public default Object getFieldTwo(){ return getDelegate().getFieldTwo(); }
public default void setFieldOne(Object o){ getDelegate().setFieldOne(o); }
public default void setFieldTwo(Object o){ getDelegate().setFieldTwo(o); }
}
/*the enums, now*/
public static enum EnumFirst implements CommonInterface_Delegating{
FieldA, FieldB, FieldC;
EnumFirst (){
setDefaultDelegate();
}
final CommonDelegator_FieldKeeper delegator;
public CommonInterface getDelegate(){ return delegator; }
public void setDelegate(CommonInterface delegator){ this.delegator=delegator; }
public void someMethod(){
/*do what You need*/
}
}
public static enum EnumSecond implements CommonInterface_Delegating{
FieldA, FieldB, FieldC;
EnumSecond (){
setDefaultDelegate();
}
final CommonDelegator_FieldKeeper delegator;
public CommonInterface getDelegate(){ return delegator; }
public void setDelegate(CommonInterface delegator){ this.delegator=delegator; }
public void someMethod(){
/*do what You need, again*/
}
}
}
【讨论】: