V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
chengfeng1992
V2EX  ›  Java

Java 枚举的继承、实现接口 及默认实现 的问题

  •  
  •   chengfeng1992 · 2018-10-31 18:40:25 +08:00 · 7424 次点击
    这是一个创建于 1997 天前的主题,其中的信息可能已经有所发展或是发生改变。

    最近在封装一个第三方类库。

    其中要用到类库中提供了很多枚举,出于 不想暴漏类库要限制类库中某些枚举值的使用 的目的,故想到了 继承一遍枚举。

    又因为 java 的枚举类型是不支持继承的(至少我这的 jre 不支持),所以想到了 使用实现接口 来达到目的。


    • 首先,类库中的枚举:
    public enum P1Enum {
        A, B, C;
    }
    
    public enum P2Enum {
        AA, BB, CC;
    }
    
    • 然后,自己写的接口
    interface IParent<T> {
        T getParent();
    }
    
    • 再然后,子类实现接口
    public enum P1S1Enum implements IParent<P1Enum> {
    
        A, B;
    
        @Override
        public P1Enum getParent() {
            return P1Enum.valueOf(this.name());
        }
    
    }
    
    public enum P1S2Enum implements IParent<P1Enum> {
    
        B, C;
    
        @Override
        public P1Enum getParent() {
            return P1Enum.valueOf(this.name());
        }
    
    }
    
    public enum P2S1Enum implements IParent<P2Enum> {
    
        AA, CC;
    
        @Override
        public P2Enum getParent() {
            return P2Enum.valueOf(this.name());
        }
    
    }
    
    
    • 这样做,确实可以实现目的

    然后问题来了,

    • 1.每一个枚举都需要 @Override getParent(), 是否可以通过接口默认实现来解决呢

    以下这一段代码不正确,因为我不会写了,当然问题就在这里。

    interface IParent<T extends Enum<T>> {
    
        default T getParent() {
            return T.valueOf(null, "A");
        }
    
    }
    
    
    • 2.有没有更好的实现方式呢

    先谢答。么么哒~

    3 条回复    2018-11-05 11:20:50 +08:00
    SoloCompany
        1
    SoloCompany  
       2018-10-31 21:07:48 +08:00
    理论上可以,只能通过反射
    因为 java 虽然是类型擦除的,但 implements / extends 把模板变量固化了
    可以通过反射获取到模板类,再使用 Enum.valueOf(type, name)
    SoloCompany
        2
    SoloCompany  
       2018-10-31 21:42:41 +08:00
    ParameterizedType t = (ParameterizedType) P1S1Enum.class.getGenericInterfaces()[0];
    assert t.getActualTypeArguments()[0] == P1Enum.class;
    zsh1995
        3
    zsh1995  
       2018-11-05 11:20:50 +08:00
    interface IParent<T extends Enum<T>> {

    String name();

    default T getParent(){
    Class<T> rawType = (Class <T>) ((ParameterizedType) getClass().getGenericInterfaces()[0]).getActualTypeArguments()[0];
    return T.valueOf(rawType, this.name());
    }
    }
    酱紫?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3003 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 11:07 · PVG 19:07 · LAX 04:07 · JFK 07:07
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.