假设您正在维护最初几年前发布的API(在Java获得enum
支持之前),并且它定义了一个枚举值为int的类:
public class VitaminType { public static final int RETINOL = 0; public static final int THIAMIN = 1; public static final int RIBOFLAVIN = 2; }
多年来,API已经发展并获得了Java 5特有的功能(通用接口等).现在您要添加一个新的枚举:
public enum NutrientType { AMINO_ACID, SATURATED_FAT, UNSATURATED_FAT, CARBOHYDRATE; }
"旧式"int-enum模式没有类型安全性,不可能添加行为或数据等,但它已发布并正在使用中.我担心混合两种枚举方式对API的用户来说是不一致的.
我看到三种可能的方法:
放弃并定义新的枚举(NutrientType
在我的虚构示例中)作为类的一系列整数VitaminType
.你得到了一致性,但你没有利用类型安全和其他现代功能.
决定在已发布的API中存在不一致:保持VitaminType
原样,并添加NutrientType
为enum
.采用a的VitaminType
方法仍然被声明为采用int,采用a的方法NutrientType
被声明为采用这种方法.
弃用VitaminType
该类并引入新的VitaminType2
枚举.将new定义NutrientType
为枚举.
恭喜,在接下来的2 - 3年内,您可以杀死已弃用的类型,您将要处理每个方法的弃用版本,这些方法VitaminType
将int作为int并添加每个方法的新foo(VitaminType2 v)
版本.您还需要为每个已弃用的foo(int v)
方法及其相应的foo(VitaminType2 v)
方法编写测试,因此您只需将QA工作倍增.
什么是最好的方法?
API消费者将VitaminType与NutrientType混淆的可能性有多大?如果不太可能,那么维持API设计的一致性可能会更好,特别是如果建立了用户群并且您希望最小化客户所需的工作/学习的增量.如果可能出现混淆,那么NutrientType应该可能成为一个枚举.
这不一定是一夜之间的彻底改变; 例如,您可以通过枚举公开旧的int值:
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并使您可以控制何时弃用旧类型以及在内部依赖于旧类型的任何代码中安排切换.
需要注意保持文字值与可能已经与旧的消费者代码内联的值保持同步.