首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >随着API的发展,处理"int enum“模式与java枚举共存的最佳方法是什么?

随着API的发展,处理"int enum“模式与java枚举共存的最佳方法是什么?
EN

Stack Overflow用户
提问于 2008-12-04 15:35:49
回答 5查看 613关注 0票数 5

假设您维护的API最初是几年前发布的(在java获得enum支持之前),它将枚举值定义为ints类:

代码语言:javascript
复制
public class VitaminType {
 public static final int RETINOL = 0;
 public static final int THIAMIN = 1;
 public static final int RIBOFLAVIN = 2;
}

多年来,API不断发展,并获得了Java 5特有的特性(泛化接口等)。现在,您将添加一个新的枚举:

代码语言:javascript
复制
public enum NutrientType {
 AMINO_ACID, SATURATED_FAT, UNSATURATED_FAT, CARBOHYDRATE;
}

“旧式”的int-enum模式没有类型安全性,没有添加行为或数据的可能性等,但它已经发布并在使用中。我担心混合两种类型的枚举对于API用户来说是不一致的。

我认为有三种可能的办法:

  • 放弃并将新枚举(在我的虚构示例中定义为NutrientType)定义为一系列in,如VitaminType类。您可以获得一致性,但是您没有利用类型安全和其他现代features.
  • Decide来处理发布的API中的不一致性:保持VitaminType的原样,并将NutrientType添加为enum。获取VitaminType的方法仍然声明为接受int,接受NutrientType的方法声明为接受VitaminType类,并引入了一个新的VitaminType2枚举。将新的NutrientType定义为枚举。

恭喜您,在接下来的2-3年中,您将处理每个以VitaminType作为int的方法的弃推荐版本,并添加每个方法的新foo(VitaminType2 v)版本。您还需要为每个不推荐的foo(int v)方法及其相应的foo(VitaminType2 v)方法编写测试,因此您只需增加QA的工作量。

什么是最好的方法?

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2008-12-04 15:49:44

个人的看法是,这可能是不值得的努力,试图改变。首先,“公共静态最终int”成语不会很快消失,因为它在JDK上随处可见。另一方面,如果您的类将编译掉引用,那么跟踪原始it的使用可能会非常不愉快,因此您很可能不会知道在为时已晚(我的意思是说)之前已经破坏了任何东西。

代码语言:javascript
复制
class A
   {
       public static final int MY_CONSTANT=1
   }

   class B
   {
           ....
           i+=A.MY_CONSTANT; 
   }

被编译成

代码语言:javascript
复制
i+=1

因此,如果您重写A,您可能永远不会意识到B是坏的,直到你重新编译B以后。

这是一个众所周知的成语,把它放在里面也许没那么可怕,当然比其他的好。

票数 3
EN

Stack Overflow用户

发布于 2008-12-04 17:09:37

API使用者把VitaminType和NutrientType混为一谈的可能性有多大?如果不太可能,那么最好保持API设计的一致性,特别是如果建立了用户基础,并且您希望尽量减少客户所需的工作/学习增量。如果可能出现混淆,那么NutrientType可能会成为一个枚举。

这不一定是一夜之间的大规模更改;例如,您可以通过enum公开旧的int值:

代码语言:javascript
复制
public enum Vitamin {

    RETINOL(0), THIAMIN(1), RIBOFLAVIN(2);

    private final int intValue;

    Vitamin(int n) {
        intValue = n;
    }

    public int getVitaminType() {
        return intValue;
    }

    public static Vitamin asVitamin(int intValue) {
        for (Vitamin vitamin : Vitamin.values()) {
            if (intValue == vitamin.getVitaminType()) {
                return vitamin;
            }
        }
        throw new IllegalArgumentException();
    }

}

/** Use foo.Vitamin instead */
@Deprecated
public class VitaminType {

    public static final int RETINOL = Vitamin.RETINOL.getVitaminType();
    public static final int THIAMIN = Vitamin.THIAMIN.getVitaminType();
    public static final int RIBOFLAVIN = Vitamin.RIBOFLAVIN.getVitaminType();

}

这允许您更新API,并在任何内部依赖旧类型的代码中对何时放弃旧类型和计划切换进行一些控制。

需要注意的是,要使文字值与那些可能与旧的使用者代码相衬的值保持同步。

票数 6
EN

Stack Overflow用户

发布于 2008-12-04 15:49:40

有传言说"make“的创建者意识到Makefiles的语法很糟糕,但是他觉得他无法改变它,因为他已经有10个用户了。

不惜一切代价的向后兼容,即使它伤害了您的客户,也是一件坏事。所以不能给你一个明确的答案,在你的情况下做什么,但要确定,并考虑您的用户的长期成本。

另外,请考虑如何重构代码的核心,将旧的基于整数的枚举只保留在外层。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/341005

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档