如何为几个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< String, Aggregation > c_LOOKUP =
        new HashMap< String, Aggregation >();
    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< String, Interval > c_LOOKUP =
        new HashMap< String, Interval >();
    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< Aggregation > c_DICTIONARY =
        new  ReverseDictionary< Aggregation >( 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< Interval > c_DICTIONARY =
        new ReverseDictionary< Interval >( 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< E >>
{
    Map< String, E > c_LOOKUP = new HashMap< String, E >();
    public ReverseDictionary( final Class< E > 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() 逻辑有点多余。 我们实际上是在指定一类枚举,在我看来,它似乎是"是"关系
为了

接口,更喜欢组合而不是继承和编程。由于枚举是类(不是常规的,但仍然是 - 类),您可以创建一些包含共享逻辑的字段,让枚举实现您的接口并将实现委托给该字段。

相关代码片段:

共享接口

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得到的最干燥的,就手头的情况而言。

import java.util.*;
interface HasName {
  public String getName();
}
class EnumEnhancer<E extends Enum<E> & HasName> {
  private Map<String, E> lookup;
  public EnumEnhancer(E... values) {
    lookup = new HashMap<String, E>();
    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<Color> enhancer = 
    new EnumEnhancer<Color>(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
    {
        X.A.foo ();
        Y.B.foo ();
    }
}
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";
    }
}

请注意,接口不知道它将由枚举实现,因此它不能在默认方法中对this使用Enum方法。但是,您可以将这些方法包含在界面本身中(就像我对name()所做的那样),然后正常使用它们。当您声明枚举时,它们将通过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 类中定义您的共同行为:

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

并在每个类中扩展它:

public SecondClass extends First {
 ...
}

最新更新