【问题标题】:How to pass generic enum key in Java code如何在 Java 代码中传递通用枚举键
【发布时间】:2016-10-06 12:58:20
【问题描述】:

我有两个类,即 ChildOneChildTwo 扩展 Base 类需要 Base 和一个名为 AgeEnum 的枚举。有一种方法,即getAge() 在子类中很常见,现在我想在基类中移动那个常用方法,我也想做一些事情,这样当我在任何一个上调用 getAge() 时 对象(例如 - ChildOne.getAge())应该返回枚举中定义的那个孩子的年龄。

  • 基类

     public class BaseClass {
        ***// Define getAge() here somehow to get the dynamic value of the*** 
     }
    
  • 儿童一班

     public class ChildOne extends BaseClass {
        public int getAge(){
            return AgeEnum.ChildAge.CHILD_ONE.getValue();
        }
     }
    
  • 儿童二班

     public class ChildTwo extends BaseClass {
        public int getAge(){
            return AgeEnum.ChildAge.CHILD_TWO.getValue();
        }
     }
    
  • 枚举

     public class AgeEnum {
        public enum ChildAge {
            CHILD_ONE(12), 
            CHILD_TWO(19);
    
            private ChildAge(final int text) {
                this.text = text;
            }
    
            private final int text;
    
            public int getValue() {
                return text;
            }
        }
     }
    

到目前为止,我已经分析了如果我们可以做这样的事情,但是如何在枚举调用中配置它,在这种情况下,如果我调用子类的getAge(),我将从枚举中获取值,我要做的就是如果该类在运行时标识子类并传递枚举常量(可能我将从上下文中获取类实例并使用反射获取类名):

     public class BaseClass {
        public int getAge(){
            return AgeEnum.ChildAge.<dynamicAgeConstent>.getValue();
        }
     }

【问题讨论】:

  • BaseClass 实例和 ChildAge 枚举之间是否存在 1:1 映射关系?
  • 为什么不把枚举作为基类的属性呢?您可以将它作为构造函数中的参数传递

标签: java spring design-patterns enums


【解决方案1】:

首先,让我们从最明显的解决方案开始。由于您的任务不假定可能存在既不是ChildOne 也不是ChildTwoBaseClass 实例,因此根本不需要将实现向上移动到类层次结构中。显然,您想让该方法在基类型中可用,通过声明基类型 abstract 可以轻松实现:

public abstract class BaseClass {
    public abstract int getAge();
}
public class ChildOne extends BaseClass {
    @Override public int getAge(){
        return AgeEnum.ChildAge.CHILD_ONE.getValue();
    }
}
public class ChildTwo extends BaseClass {
    @Override public int getAge(){
        return AgeEnum.ChildAge.CHILD_TWO.getValue();
    }
}

一般来说,可以并建议对代码进行结构化以尽量减少代码重复,例如

public abstract class BaseClass {
    public int getAge() {
        return childAge().getValue();
    }
    abstract AgeEnum.ChildAge childAge();
}
public class ChildOne extends BaseClass {
    @Override AgeEnum.ChildAge childAge() {
        return AgeEnum.ChildAge.CHILD_ONE;
    }
}
public class ChildTwo extends BaseClass {
    @Override AgeEnum.ChildAge childAge() {
        return AgeEnum.ChildAge.CHILD_TWO;
    }
}

但是在这里,代码重复是如此之少,以至于现在有两种方法不值得增加复杂性。

为了完整起见,可以将这些关联设置为子类的固定static 属性,可由基类实现查询

public abstract class BaseClass {
    @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE)
    @interface Age { AgeEnum.ChildAge value(); }

    public int getAge() {
        return getClass().getAnnotation(Age.class).value().getValue();
    }
}

@Age(AgeEnum.ChildAge.CHILD_ONE)
public class ChildOne extends BaseClass {
}

@Age(AgeEnum.ChildAge.CHILD_TWO)
public class ChildTwo extends BaseClass {
}

但是,在这些简单的情况下,提高的复杂性是否会得到回报,这又是一个问题。我认为,您只需要将基类设为abstract,就像在第一个示例中一样……

【讨论】:

    【解决方案2】:

    一种方法是让enum 成为基类的一个属性。该属性可能作为基类构造函数的参数出现:

    public class BaseClass {
    
        private final AgeEnum.ChildAge age;
    
        public BaseClass(AgeEnum.ChildAge age) {
            this.age = age;
        }
    
        public int getAge() {
            return this.age.getValue();
        }
    }
    

    然后,子类只需要指定正确的枚举:

    public class ChildOne extends BaseClass {
    
        public ChildOne() {
            super(AgeEnum.ChildAge.CHILD_ONE);
        }
    }
    

    还有:

    public class ChildTwo extends BaseClass {
    
        public ChildTwo() {
            super(AgeEnum.ChildAge.CHILD_TWO);
        }
    }
    

    【讨论】:

      【解决方案3】:

      你可以通过名字来获取枚举常量,比如

      ChildAge enumConstant = ChildAge.valueOf("CHILD_ONE");
      

      然后你可以使用类似的东西:

      System.out.println(ChildAge.valueOf("CHILD_ONE").getValue());
      

      打印 12。

      如果你真的想将你的子类“连接”到一个枚举常量,我会简单地对它们进行硬编码,因为你也(只能)对子类进行硬编码。

      【讨论】:

        猜你喜欢
        • 2011-04-29
        • 2023-03-24
        • 1970-01-01
        • 1970-01-01
        • 2019-01-28
        • 1970-01-01
        • 1970-01-01
        • 2021-07-25
        • 1970-01-01
        相关资源
        最近更新 更多