【问题标题】:How to inherit functionalities to reduce repeating codes in enums?如何继承功能以减少枚举中的重复代码?
【发布时间】:2019-12-21 12:27:30
【问题描述】:

在我正在处理的 Java 应用程序中,我有许多枚举,它们最终在其中包含一个静态 fromString 方法,用于将字符串转换为其实际枚举值。

所以,我想我可以有一个“基”类,我的所有枚举都可以从中扩展,而不必一直重复该代码。由于枚举不能扩展类,我计划做的是我可以通过接口来做到这一点。

我拥有的是以下内容:

public interface IBaseEnum {

    String enumVal = null;

    public static <T extends Enum<T> & IBaseEnum> Enum<T> fromString(String strVal) {
        if (strVal == null) return null;
        // T.values() has error because T is not recognised to have the method values()
        for (T myEnum : T.values()) {
            if (myEnum.enumVal.equals(strVal.toUpperCase())) {
                return myEnum;
            }
        }
        return null;
    }
}

然后,为了继承该静态方法,我将在我的实际 Enum 中实现 IBaseEnum

public enum Colour implements IBaseEnum {
   Red("red");
   //...
}

但是,IBaseEnum 中的类型存在问题。 T.values() 行有错误,因为泛型类型 T 无法引用回枚举本身,因此它抱怨找不到方法 values()

这是继承枚举功能的正确方法吗?否则,我如何继承枚举中的方法,这样我就不必在每个枚举中复制/粘贴和重复相同的一组方法?

【问题讨论】:

  • 我最初的想法是,您想要实现的目标将导致“滥用”枚举。如果要使用继承,请使用类。如果要将类型抽象为“值列表”,请使用枚举。顺便说一句,您正在寻找的方法不是 .valueOf() 吗? (另见:howtodoinjava.com/java/enum/enum-tutorial

标签: java enums


【解决方案1】:

您的代码无法运行的原因有几个,我应该提一下:

  • String enumVal = null;IBaseEnum 是一个接口,numVal 获得隐含的 publicstaticfinal 修饰符。但是,您打算将 enumVal 用作实例属性。
  • T.values():当然这不会编译。但即使它可以(或者你有类实例),你仍然无法使这个动态化。静态方法是在编译时选择的。让它动态工作的唯一方法(我知道)是使用反射,当然是传入枚举的类对象。

因为您希望能够调用Color.fromString(...),所以您别无选择,只能在每个枚举类中将其声明为静态方法。话虽如此,我认为您可以从逻辑中重用最多的是查找代码(同样,除非您使用反射)。

要重用查找逻辑,您可以更改IBaseEnum 的协定,使其声明一个返回enumVal 值的方法。除此之外,values() 方法可以由枚举类本身调用。下面是它的样子:

interface IBaseEnum {

    String enumVal();

    public static <T extends Enum<T> & IBaseEnum> T 
                 fromString(String strVal, T[] values) {

        if (strVal == null)
            return null;

        for (T myEnum : values) {
            if (myEnum.enumVal().equalsIgnoreCase(strVal)) {
                return myEnum;
            }
        }

        return null;
    }
}

这将导致一个像下面这样的枚举类:

enum Colour implements IBaseEnum {
    VAL1("string")
    ;

    private final String val;

    Colour(String v) {
        this.val = v;
    }

    @Override
    public String enumVal() {
        return this.val;
    }

    public static Colour fromString(String s) {
        return IBaseEnum.fromString(s, values());
    }
}

记住:如果enumVal() 打算只返回枚举字面量,那么您可以通过使用所有枚举中可用的valueOf 方法来摆脱所有这些复杂性。仅当您的值的比较需要自定义逻辑时才执行此操作。

【讨论】:

    猜你喜欢
    • 2013-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多