如何在 Swift 中存储通用测量值?

How to store a generic Measurement in Swift?

我想要一个可以表示单个 Measurement 但可能具有不同单位类型的变量。例如,它可以存储长度或质量。看起来很简单,但是我想不通

这是我尝试过的:

struct Data {
    var weight: Measurement<UnitMass>
    var length: Measurement<UnitLength>
    var target = "Weight"

    var valueOfTarget: Measurement<Unit> {
        if target == "Weight" {
            return weight
        } else {
            return length
        }
    }
}

var data = Data(weight: Measurement<UnitMass>(value: 10, unit: UnitMass.kilograms),
                length: Measurement<UnitLength>(value: 10, unit: UnitLength.centimeters),
                target: "Weight")

print(data.valueOfTarget)

我也尝试按照另一个答案中的建议使用 <Dimension>,但出现了类似的错误。

这会导致编译器错误:

error: cannot convert return expression of type 'Measurement<UnitMass>' to return type 'Measurement<Unit>'

我是不是遗漏了一些明显的东西,或者这是不可能的?

您可以创建新的通用 return 值。这对我来说似乎编译正常。

struct Data {
    var weight: Measurement<UnitMass>
    var length: Measurement<UnitLength>
    var target = "Weight"

    var valueOfTarget: Measurement<Unit> {
        if target == "Weight" {
            return Measurement<Unit>(value: weight.value, unit: weight.unit)
        } else {
            return Measurement<Unit>(value: length.value, unit: length.unit)
        }
    }
}

var data = Data(weight: Measurement<UnitMass>(value: 10, unit: UnitMass.kilograms),
                length: Measurement<UnitLength>(value: 10, unit: UnitLength.centimeters),
                target: "Weight")

print(data.valueOfTarget)

首先,不要创建自己的名为 Data 的结构,因为 Foundation 已经有一个名为 Data 的类型,它被广泛使用。

其次,因为(在评论中)你说“这是为了减肥,用户可以选择一个目标作为体重或腰围尺寸”,看来你应该使用 enum 而不是 struct:

enum WeightLossTarget {
    case weight(Measurement<UnitMass>)
    case waistSize(Measurement<UnitLength>)
}

第三,如果你真的需要使用struct,你可以退回到Objective-C类型NSMeasurement非通用类型:

struct WeightLossTarget {
    enum TargetType {
        case weight
        case waistSize
    }

    var weight: Measurement<UnitMass>
    var waistSize: Measurement<UnitLength>
    var target: TargetType

    var valueOfTarget: NSMeasurement {
        switch target {
        case .weight: return weight as NSMeasurement
        case .waistSize: return waistSize as NSMeasurement
        }
    }
}