使用自定义设置器和计算结构属性的两种方式转换

Two way conversion using custom setters and computed struct properties

我创建了一个结构来根据给定的比例涵盖豆类和水之间的转换。这是我目前如何定义这个

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

这只能以一种方式起作用,即给定或更改 bean。我如何扩展结构以允许在更改水值时计算和设置 bean?

想要的结果

cup.water = Measurement(value: 260, unit: .milliliters) // should set water and compute beans
print (cup.beans) // 20.0 mg

因为你有相互依赖的变量,你不能直接使用计算属性,因为你需要能够存储 'other' 项的值。

您可以使用私有后备变量来存储值和 setter/getter 代码 update/retrieve 这些。

您还需要实施特定的初始化器,因为您不能再依赖自动成员初始化器。

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

请注意,我还修改了您的公式,以确保使用正确的单位。