如何为一些Java枚举添加常用方法? (抽象类祖先?)

我有一些Java枚举

public enum Aggregation { MORTGAGE( "Mortgage" ), POOLS( "Pools" ), PORTFOLIO( "Portfolio" ); private Aggregation( final String name ) { m_Name = name; } private String m_Name; static Map c_LOOKUP = new HashMap(); static { for (Aggregation agg:values()){ c_LOOKUP.put(agg.m_Name,agg); } } public Aggregation lookup(String name){ return c_LOOKUP.get( name ); } @Override public String toString() { return m_Name; } } public enum Interval { MONTHLY( "Monthly" ), QUARTLY( "Quartly" ), SEMIANNUALLY( "SemiAnnually" ), ANNUALLY("Annually"); private Interval( final String name ) { m_Name = name; } private String m_Name; static Map c_LOOKUP = new HashMap(); static { for (Interval agg:values()){ c_LOOKUP.put(agg.m_Name,agg); } } public Interval lookup(String name){ return c_LOOKUP.get( name ); } @Override public String toString() { return m_Name; } } 

如您所见,这里有相当多的代码重复。 如果有一种方法可以引入类似抽象共同祖先类的东西,那就太好了。 但java枚举不能固有。 什么是最好的方法? 谢谢。


编辑:我已经找到了类似ŁukaszBachman和missingfacktor的版本

 static public enum Aggregation { MORTGAGE( "Mortgage" ), POOLS( "Pools" ), PORTFOLIO( "Portfolio" ); private final String m_Name; final static private ReverseDictionary c_DICTIONARY = new ReverseDictionary( Aggregation.class ); static public Aggregation lookup( final String name ) { return c_DICTIONARY.lookup( name ); } private Aggregation( final String name ) { m_Name = name; } @Override public String toString() { return m_Name; } } static public enum Interval { MONTHLY( "Monthly" ), QUARTLY( "Quartly" ), SEMIANNUALLY( "SemiAnnually" ), ANNUALLY( "Annually" ); private final String m_Name; final static private ReverseDictionary c_DICTIONARY = new ReverseDictionary( Interval.class ); static public Interval lookup( final String name ) { return c_DICTIONARY.lookup( name ); } private Interval( final String name ) { m_Name = name; } @Override public String toString() { return m_Name; } } static public class ReverseDictionary< E extends Enum> { Map c_LOOKUP = new HashMap(); public ReverseDictionary( final Class enumClass ) { for( final E agg : EnumSet.allOf( enumClass ) ) { c_LOOKUP.put( agg.toString(), agg ); } } public E lookup( final String name ) { return c_LOOKUP.get( name ); } } 

我看到了一些推理。 但是,它仍然不是很令人满意。

  1. 由于返回类型不同,很难为lookup(String)定义接口
  2. 我可以理解, lookup(String)并不是真正的重复而是规范,但我仍然认为m_Name字段和toString()逻辑有点多余。 我们确实指定了一类枚举,在我看来它似乎是“是一种”关系。

为了接口,支持 组合而不是inheritance编程 。 由于Enums是类(不是常规的,但仍然是 – 类),您可以创建一些包含共享逻辑的字段,让enum实现您的接口并将实现委托给该字段。

相关代码段:

共享界面

 public interface MyInterface { void someMethod(); } 

逻辑实施

 public class MyInterfaceImpl implements MyInterface { public void someMethod() { System.out.println("Do smth..."); } } 

第一个枚举

 public enum EnumA implements MyInterface { ; private MyInterface impl = new MyInterfaceImpl(); public void someMethod() { impl.someMethod(); } } 

第二个枚举

 public enum EnumB implements MyInterface { ; private MyInterface impl = new MyInterfaceImpl(); public void someMethod() { impl.someMethod(); } } 

请注意EnumAEnumB不是真正的代码重复,因为这是普通的委托(在我看来是有效的)。 另请注意,通过使用界面,一切都很好地粘在一起。

以下是如何使用合成和委派来解决您的问题。 (对于手头的情况,我认为这是你可以用Java获得的DRY 。)

 import java.util.*; interface HasName { public String getName(); } class EnumEnhancer & HasName> { private Map lookup; public EnumEnhancer(E... values) { lookup = new HashMap(); for (E e : values) { lookup.put(e.getName(), e); } } public E lookup(String name) { return lookup.get(name); } public String toString(E e) { return e.getName(); } } enum Color implements HasName { // This is interface inheritance. RED("red"), GREEN("green"), BLUE("blue"); // This is composition. private static final EnumEnhancer enhancer = new EnumEnhancer(values()); private String name; private Color(String name) { this.name = name; } public String getName() { return name; } // This is delegation. public String toString() { return enhancer.toString(this); } // This too is delegation. public static Color lookup(String name) { return enhancer.lookup(name); } } class Main { public static void main(String[] args) { System.out.println(Color.lookup("blue")); // prints blue } } 

您可以使用Java 8默认接口方法实现此目的:

 public class test { public static void main (String[] arguments) throws Exception { XAfoo (); YBfoo (); } } interface MyEnumInterface { String getCommonMessage (); String name (); default void foo () { System.out.println (getCommonMessage () + ", named " + name ()); } } enum X implements MyEnumInterface { A, B; @Override public String getCommonMessage () { return "I'm an X"; } } enum Y implements MyEnumInterface { A, B; @Override public String getCommonMessage () { return "I'm an Y"; } } 

请注意,接口不知道它将由枚举实现,因此它不能在默认方法中使用Enum方法。 但是,您可以在界面本身中包含这些方法(就像我使用name() ),然后正常使用它们。 当您声明Enum时, Enum将为您“实施”它们。

如何使用包含常用函数的静态助手类,从枚举方法中调用它们。

关于你对toString()的评论。

 public enum MyEnum{ ONE("one"); public MyEnum(String m_Name){ this.m_Name = m_Name; } public String toString(){ return m_Name; } String m_Name; } 

在First Class中定义您的常见behviur:

 public class First { public String name() { return "my name"; } ... } 

而不是在每个类中扩展它:

 public SecondClass extends First { ... }