I created a struct to cover the conversion between beans and water based on a given ratio. Here's how I currently defined this
public struct Coffee {
public var ratio:Double
public var beans:Measurement<UnitMass>
public var water:Measurement<UnitVolume> {
return Measurement(value: (beans.value * ratio), unit: .milliliters)
}
}
var cup = Coffee(ratio: 13.0, beans: Measurement(value: 30, unit: UnitMass.milligrams))
let computedWater = cup.water // 390 mL
This only works in one way, given or changing the beans. How can I extend the struct to also allow compute and setting the beans when the water value is being changed?
cup.water = Measurement(value: 260, unit: .milliliters) // should set water and compute beans
print (cup.beans) // 20.0 mg
Since you have inter-dependent variables, you can't use computed properties directly, as you need to be able to store the value of the 'other' item.
You can use private backing variables to store the values and setter/getter code to update/retrieve these.
You also need to implement specific initialisers as you can no longer rely on the automatic memberwise initialiser.
public struct Coffee {
private var _beans: Measurement<UnitMass>!
private var _water: Measurement<UnitVolume>!
public var ratio:Double
public var beans:Measurement<UnitMass> {
set {
_beans = newValue
_water = Measurement(value: (_beans.converted(to: .milligrams).value * ratio), unit: .milliliters)
}
get {
return _beans
}
}
public var water:Measurement<UnitVolume> {
set {
_water = newValue
_beans = Measurement(value: _water.converted(to: .milliliters).value * (1/ratio)), unit: .milligrams)
}
get {
return _water
}
}
init(ratio: Double, beans: Measurement<UnitMass>) {
self.ratio = ratio
self.beans = beans
}
init(ratio: Double, water: Measurement<UnitVolume>) {
self.ratio = ratio
self.water = water
}
}
var cup = Coffee(ratio: 13.0, beans: Measurement(value: 30, unit: UnitMass.milligrams))
let computedWater = cup.water // 390 mL
print (cup.water)
cup.water = Measurement(value: 260, unit: .milliliters) // should set water and compute beans
print (cup.beans) // 20.0 mg
cup.water = Measurement(value: 0.26, unit: .liters)
print (cup.beans) // 20.0 mg
Note that I have also modified your formulas so that they ensure that the correct units are used.