skip to Main Content

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 ?

2

Answers


  1. I would prefer extension for this.

    class MyModel {
      const MyModel(this.valueInCM);
    
      ///* in minimum  unite, e.g for your domain level,
      /// we can consider from cm, if needed you goes down too
      final double valueInCM;
    }
    
    extension MyModelExt on MyModel {
      double get toMeter => valueInCM / 100;
      double get toKM => valueInCM / 1000;
    }
    

    Also you can checkout Duration class in dart.

    Login or Signup to reply.
  2. 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

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search