【问题标题】:Kotlin generic function for Float and Double浮点和双精度的 Kotlin 通用函数
【发布时间】:2020-03-21 19:29:46
【问题描述】:

以下函数可以编译,但只能与 Doubles 一起使用:

fun triang(x: Double): Double {
    var m = x - truncate(x)
    if (m < 0) m += 1.0
    return when {
        m < 0.25 -> 4.0 * m
        m < 0.50 -> 2.0 - 4.0 * m
        m < 0.75 -> 2.0 - 4.0 * m
        else -> 4.0 * m - 4.0
    }
}

我也希望能够将该函数与 Floats 一起使用,因此我尝试将其设为通用函数:

fun <T: Number> triang(x: T): T {
    var m = x.toDouble() - truncate(x.toDouble())
    if (m < 0) m += 1.0
    return when {
        m < 0.25 -> 4.0 * m
        m < 0.50 -> 2.0 - 4.0 * m
        m < 0.75 -> 2.0 - 4.0 * m
        else -> 4.0 * m - 4.0
    } as T // problem here
}

但这不起作用,因为转换为 T 会导致警告“未经检查的转换:双倍转换为 T”。

如何正确地为 Float 和 Double 编写通用函数?

【问题讨论】:

  • 一种方法是通过重载fun triang(x: Float) = triang(x.toDouble()).toFloat()。这正是您的通用实现要做的事情。我知道这不能回答你的问题。但它比泛型实现更安全,因为它不适用于其他 Number 类型。
  • 是的,我最终可能会这样做。但我仍然对泛型是否可以做到这一点感兴趣。
  • 不,因为没有办法将Double 转换回T(既不是你尝试的演员也不是方法);至少没有测试所有类型(如when(x) { is Double -&gt; ...; is Float -&gt; ...; ... }
  • 你可以试试inline fun &lt;reified T : Number&gt; ...,这会允许演员,但它总是会因为拳击而失败(Double除外)。

标签: generics kotlin generic-function


【解决方案1】:

Kotlin 不支持像 Java 这样的数字类型转换,并且没有明确的方法可以将数字转换为擦除数字类型。对 Double 和 Float 重载方法要好得多。

但是,你可以取消这个警告,因为实际上这段代码会先将返回值转换为 Number,然后它会从中调用&lt;number type&gt;Value,但这不是很好,因为这个函数不是为整数值设计的如果调用triang(1),会导致结果精度损失。

【讨论】:

    猜你喜欢
    • 2018-02-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-06
    • 1970-01-01
    • 2013-02-09
    相关资源
    最近更新 更多