Dart中枚举能否共享具体方法以避免代码重复?
优化单位转换枚举的重复逻辑方案
问题背景
我使用带有枚举类型unit属性的值对象,这些枚举实现接口以支持单位转换(如厘米转米、千克转克等)。示例代码如下:
class Height { final double value; final DistanceUnit unit; const Height({required this.value, this.unit = DistanceUnit.cm}); }
// 限制仅枚举能实现此接口,这对其他方法很重要 abstract interface class Convertible implements Enum { final double factor; Convertible({required this.factor}); double getConversionFactor(covariant Convertible from, covariant Convertible to); } enum DistanceUnit implements Convertible { cm(factor: 1/100), m(factor: 1); @override final double factor; const DistanceUnit({required this.factor}); @override double getConversionFactor(covariant Convertible from, covariant Convertible to) { return from.factor / to.factor; } }
当前代码运行正常,但由于存在面积、距离、体积、时间、质量等多种单位,getConversionFactor()方法需重复编写,违反了DRY原则。已知枚举继承自Enum且无法扩展其他类,需要优化方案。
优化方案
方案1:给Convertible接口添加默认方法
Dart 2.17及以上版本支持抽象接口类定义默认方法,我们可以把getConversionFactor的通用逻辑直接内嵌到接口中,所有实现Convertible的枚举会自动继承这个方法,无需重复编写。
修改后的Convertible接口:
abstract interface class Convertible implements Enum { final double factor; Convertible({required this.factor}); // 通用转换逻辑作为默认方法实现 double getConversionFactor(covariant Convertible from, covariant Convertible to) { return from.factor / to.factor; } }
后续新增单位枚举时,只需要实现Convertible并定义factor即可:
enum MassUnit implements Convertible { g(factor: 1/1000), kg(factor: 1); @override final double factor; const MassUnit({required this.factor}); // 无需重写getConversionFactor,直接使用接口默认实现 }
方案2:用扩展方法提取通用逻辑
如果不想修改原有接口结构,可以通过扩展方法把转换逻辑抽离出来,作用于所有实现Convertible的枚举:
// 定义扩展方法 extension ConvertibleExtension on Convertible { double getConversionFactor(covariant Convertible from, covariant Convertible to) { return from.factor / to.factor; } }
此时Convertible接口可以移除getConversionFactor的声明:
abstract interface class Convertible implements Enum { final double factor; Convertible({required this.factor}); }
调用时直接通过扩展方法使用:
// 示例:厘米转米 final cm = DistanceUnit.cm; final m = DistanceUnit.m; print(cm.getConversionFactor(cm, m)); // 输出0.01
方案对比
- 方案1更贴合接口设计的职责内聚原则,代码结构更直观,推荐优先使用。
- 方案2属于无侵入式扩展,适合无法修改原有接口的场景。
两种方案都能彻底消除重复代码,符合DRY原则,完美适配Dart枚举不能继承类的限制。
内容的提问来源于stack exchange,提问作者Galactose
相关产品推荐
相关产品推荐

