我有一些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 );
}
}
我看到了一些推理。但是,它仍然不是很令人满意。
lookup(String)
定义接口lookup(String)
并不是真正的重复而是规范,但我仍然认为m_Name字段和toString()逻辑有点多余。我们确实指定了一类枚举,在我看来似乎是“is-a”关系。 答案 0 :(得分:14)
为了接口而支持组合优于继承和编程。由于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();
}
}
请注意EnumA
和EnumB
并非真正的代码重复,因为这是普通的委托(在我看来是有效的)。另请注意,使用界面可以很好地粘合在一起。
答案 1 :(得分:5)
以下是如何使用合成和委派来解决您的问题。 (对于手头的情况,我认为这是你可以用Java获得的DRY。)
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
}
}
答案 2 :(得分:4)
您可以使用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";
}
}
请注意,界面并不知道它将由枚举实现,因此它无法在默认方法中使用Enum
上的this
方法。但是,您可以在界面本身中包含这些方法(就像我对name()
所做的那样),然后正常使用它们。他们将被实施&#34;当你声明一个枚举时,由Enum
为你。
答案 3 :(得分:0)
如何使用包含常用函数的静态助手类,从枚举方法中调用它们。
关于你对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;
}
答案 4 :(得分:-1)
只需在头等舱中定义您的共同点:
public class First {
public String name() {
return "my name";
}
...
}
而不是在每个班级中扩展它:
public SecondClass extends First {
...
}