How to represent magnitude for mass in Swift?

后端 未结 3 919
甜味超标
甜味超标 2021-01-06 13:31
// SI units
enum Magnitude : Measurement {
    case Milli = Measurement(-3, \"ml\")
    case Centi = Measurement(-2, \"cl\")
    case Desi = Measurement(-1, \"dl\")
         


        
3条回答
  •  迷失自我
    2021-01-06 14:10

    If you want to be able to specify the unit of the mass with a String perhaps you could use String to represent the shorthand name and variables to give you more information about the unit, such as magnitude. Here's an example:

    1. MassUnit

    enum MassUnit: String {
        case Milligrams = "mg"
        case Grams      = "g"
        case Kilos      = "kg"
        case Tons       = "t"
    
        var magnitude: Int {
            let mag: Int
    
            switch self {
                case .Milligrams: mag = -3
                case .Grams     : mag =  0
                case .Kilos     : mag =  3
                case .Tons      : mag =  6
            }
    
            return mag
        }
    
    
        static func ordersOfMagnitudeFrom(unit1: MassUnit, to unit2: MassUnit) -> Int {
            return unit1.magnitude - unit2.magnitude
        }
    }
    
    extension MassUnit: Printable {
        var description: String {
            return self.rawValue
        }
    }
    

    2. Then, for storing actual masses you could use a Struct, which could also handle the conversions. For example:

    struct Mass {
        var value : Double
        var unit  : MassUnit
    
        static func convertMass(mass: Mass, toUnit unit: MassUnit) -> Mass {
            let ordersOfMagnitude = MassUnit.ordersOfMagnitudeFrom(mass.unit, to: unit)
    
            let multipler = pow(10.0, Double(ordersOfMagnitude))
    
            return Mass(value: mass.value * multipler, unit: unit)
        }
    
        //  Returns an optional Mass because we can't know for sure 
        //  unitString will represent a MassUnit.
        static func convertMass(mass: Mass, toUnit unitString: String) -> Mass? {
            if let unit = MassUnit(rawValue: unitString) {
                return convertMass(mass, toUnit: unit)
            }
    
            return nil
        }
    }
    
    extension Mass {
        init?(value: Double, _ unitString: String) {
            if let unit = MassUnit(rawValue: unitString) {
                self = Mass(value: value, unit: unit)
            } else {
                return nil
            }
        }
    }
    
    extension Mass : Printable {
        var description: String {
            return "\(value) \(unit)"
        }
    }
    

    3. Then you can use the masses and units:

    if let mass = Mass(value: 1, "kg"),
       let convertedMass = Mass.convertMass(mass, toUnit: "g") {
    
        println("\(mass) converted to \(MassUnit.Grams) equals \(convertedMass)")
    
        // Prints: 1.0 kg converted to g equals 1000.0 g
    }
    

    However if you use a unitString that isn't convertible to a MassUnit (either when creating or converting) nil will be returned. For example:

    let mass = Mass(value: 1, "NotAUnit") // nil
    

提交回复
热议问题