如何从函数中 return 未指定的测量值 <T>?

How do I return an unspecified Measurement<T> from a function?

更新:好的,我很困惑。我的原始代码没有编译。在将其简化为最小示例的某个时刻,它显然开始起作用了。我已经重写了原始版本,现在我已经忘记了为什么它首先不起作用。打算将此问题标记为已解决。


我想弄清楚如何编写一个 returns 任意测量值的函数,而不必事先指定测量值的 UnitType。以下或多或少是我想做的,但它不编译。 (函数的参数无关紧要。)

   func getValue(for x:Int) -> Measurement<Unit>? {
        if x==1 {
            return Measurement(value:5, unit:UnitSpeed.metersPerSecond)
        } else {
            return Measurement(value:2, unit:UnitLength.meters)
        }
    }

我不想关心单位是什么!测量封装了他们的单位,我想做的就是将它插入类似的东西:另一端的Text(reading?.unit.symbol ?? "")

func getValue(for measure:TrackedMeasure) -> some Measurement? {}抱怨"Reference to generic type 'Measurement' requires arguments in <…>"

建议的修复是 func getValue(for measure:TrackedMeasure) -> some Measurement<Unit>? { },然后抱怨 "An 'opaque' type must specify only 'Any', 'AnyObject', protocols, and/or a base class"

似乎 没有测量协议,我不知道如何定义它。

我是否必须重新实施 Measurement 才能使这项工作正常进行?

enum TrackMeasure {
    case speed
    case distance
    case time
}

func getValue(for measure: TrackMeasure) -> Measurement<Unit> {

    switch measure {
        case .speed:
            return Measurement(value: 60, unit: UnitSpeed.milesPerHour)
        case .distance:
            return Measurement(value: 10, unit: UnitLength.miles)
        case .time:
            return Measurement(value: 6, unit: UnitDuration.minutes)
    }
}

let speed = getValue(for: .speed)
let distance = getValue(for: .distance)
let time = getValue(for: .time)

Measurement<UnitType> 是一个通用类型,它不扩展公共基础 class 或符合公共协议,因此具体类型 Measurement<UnitLength>Measurement<UnitSpeed>.

绕过它的唯一方法是执行类型擦除之类的操作,并让它们都符合通用协议 AnyMeasurement:

protocol AnyMeasurement {
  var baseUnit: Unit { get }
  var value: Double { get }
}

那么你可以让Measurement符合AnyMeasurement:

extension Measurement: AnyMeasurement {
  // just need to return a base Unit, instead of a concrete UnitType
  // value: Double { get } is already implemented by Measurement
  var baseUnit: { self.unit }
}

然后,你可以这样做:

func randomMeasurement() -> AnyMeasurement {
   let speed  = Measurement(value: 10, unit: UnitSpeed.metersPerSecond)
   let length = Measurement(value: 10, unit: UnitLength.meters)

   return Bool.random() ? speed : length
}

print(randomMeasurement().baseUnit.symbol)