Search code examples
flutterdart

Can enums share concrete methods to avoid repetition?


I use value objects that have a [unit] property that is a enum. My enums implement an interface to permit conversion between units (cm to m, kg to g, etc...)

Like this :

class Height {
  final double value;
  final DistanceUnit unit;
  
  const Height({required this.value, this.unit = DistanceUnit.cm});
}
// Directly implementing Enum so that only enums can implement this ; important for another method.
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;
  }
}

This work very well but as I have many units (area, distance, volume, time, mass...) it becomes very verbose and repetitive. The getConversionFactor() method is always the same... So we are far away from the DRY advice !

I know enums inherit from Enum and cannot extend another class. But is there another way to prevent this and optimize my code ?


Solution

  • I can't get the full case inside my head but if are looking for removing the reddest for getConversionFactor just you can use mixin as below

    class Height {
    final double value;
    final DistanceUnit unit;
    
    const Height({required this.value, this.unit = DistanceUnit.cm});
    }
    // Directly implementing Enum so that only enums can implement this ; important for another method.
    abstract interface class Convertible implements Enum {
    final double factor;
    
    Convertible({required this.factor});
    
    
    }
    
    enum DistanceUnit  with Conver implements Convertible{
    cm(factor: 1/100),
    m(factor: 1);
    
    @override
    final double factor;
    
    const DistanceUnit({required this.factor});
    }
    mixin Conver  {
    double getConversionFactor(covariant Convertible from, covariant Convertible to) {
     return from.factor / to.factor;
    }
    }
    

    I think you may try another way by using map (data structure) you can consider this solution