内联类的常用方法和运算符在Kotlin中用作度量单位

时间:2018-12-07 02:25:40

标签: kotlin

我正在考虑使用Kotlin的内联类来表达带有度量单位的类型安全操作。例如,让我们定义距离,时间和速度的单位:

inline class Meters(val v: Float) {
    operator fun plus(other: Meters) = Meters(v + other.v)
    operator fun times(amount: Float) = Meters(v * amount)
    operator fun compareTo(other: Meters) = v.compareTo(other.v)
    operator fun div(other: Meters): Float = v / other.v

    fun calcSpeed(time: Seconds) = MetersPerSecond(v * time.v)
    // operator fun times(time: Seconds) = MetersPerSecond(v / time.v) // clash (for now?)
}

inline class Seconds(val v: Float) {
    operator fun plus(other: Seconds) = Seconds(v + other.v)
    operator fun times(amount: Float) = Seconds(v * amount)
    operator fun compareTo(other: Seconds) = v.compareTo(other.v)
    operator fun div(other: Seconds): Float = v / other.v

    fun calcSpeed(distance: Meters) = MetersPerSecond(distance.v / v)
}

inline class MetersPerSecond(val v: Float) {
    operator fun plus(other: MetersPerSecond) = MetersPerSecond(v + other.v)
    operator fun times(amount: Float) = MetersPerSecond(v * amount)
    operator fun compareTo(other: MetersPerSecond) = v.compareTo(other.v)

    fun calcDistance(time: Seconds) = Meters(v * time.v)
    fun calcTime(distance: Meters) = Seconds(distance.v / v)
}

这里的想法是为以下两种操作定义方法:

  1. 保持单位不变(例如:求和,乘纯 值)
  2. 得出纯值(例如:相同值的除法) 单位)
  3. 得出另一个已定义单位的值(例如:time * distance = speed

这样一来,人们就可以像这样写表达式:

val distance = Meters(1f)
val time = Seconds(1f)
val speed: MetersPerSecond = (distance * 0.5f).calcSpeed(time)

看看示例中属于情况1和2的运算符,我可以清楚地看到一个模式,并且我想知道是否有一种方法可以针对需要此操作的所有类型以更通用的方式定义一次这些方法。 “度量单位”行为。

我考虑过要有一个通用的接口,并将运算符定义为具有泛型的扩展函数:

interface UnitOfMeasurement { val v: Float }
operator fun <T: UnitOfMeasurement> T.plus(other: T) = T(v + other.v)

但是,这当然是行不通的,因为我无法实例化这样的泛型。有什么办法可以做到这一点?

0 个答案:

没有答案