【问题标题】:Generic function for all number-like values?所有类似数字的值的通用函数?
【发布时间】:2020-12-29 08:06:25
【问题描述】:

我想编写一个适用于任意类型的通用 Kotlin 函数,只要它们支持一些基本的数字运算,例如比较和加法。像这样的东西(注意:这段代码不能编译):

fun <T : ???> twiceTheLarger(a: T, b: T) = if (a > b) a + a else b + b;

在 C++ 中,这种代码可以工作。以下 C++ twiceTheLarger 函数采用支持 +&gt; 运算符的任何内容,无论是原始数字类型还是自定义类:

#include <iostream>

template <typename T> T twiceTheLarger(T a, T b) {
  return a > b ? a + a : b + b;
}

int main() {
  std::cout << twiceTheLarger(1, 2) << std::endl; // int values
  std::cout << twiceTheLarger(42.0, 1.0) << std::endl; // double values
}

如何在 Kotlin 中获得类似的结果?到目前为止,我能想到的最好方法是显式传递具有所需功能的对象,如下所示:

interface NumericOperators<T> {
    fun plus(a: T, b: T): T
    fun greaterThan(a: T, b: T): Boolean
}

object IntNumericOperators : NumericOperators<Int> {
    override fun plus(a: Int, b: Int) = a + b
    override fun greaterThan(a: Int, b: Int) = a > b
}

object DoubleNumericOperators : NumericOperators<Double> {
    override fun plus(a: Double, b: Double) = a + b
    override fun greaterThan(a: Double, b: Double) = a > b
}

fun <T> twiceTheLarger(a: T, b: T, operators: NumericOperators<T>) =
    if (operators.greaterThan(a, b)) operators.plus(a, a) else operators.plus(b, b)

fun main() {
    println(twiceTheLarger(1, 2, IntNumericOperators)) // int values
    println(twiceTheLarger(42.0, 1.0, DoubleNumericOperators)) // double values
}

有没有更好的办法?

编辑:

我意识到我可以为每个原始数字类型创建重载。问题是我正在编写一个库函数,它需要使用 arbitrary 类数字类型,甚至是我的库不知道的类型。因此,特定类型的重载不是一种选择。

【问题讨论】:

    标签: kotlin generics


    【解决方案1】:

    您需要为每个原始类型创建函数。你不能使用&lt;T : Number&gt;,尽管 Kotlin 中的所有数字都继承了这一点。 Number 超类仅用于铸件。

    您需要创建函数或扩展函数:

    fun Int.twiceTheLarger(a: Int, b: Int) = if (a &gt; b) a + a else b + b;

    fun Double.twiceTheLarger(a: Double, b: Double) = if (a &gt; b) a + a else b + b;

    如果您可以在另一个函数中使用Comparable&lt;T&gt; 进行比较,那就太好了。 T 的类型也需要重载 operator fun plus(other: T)

        interface Addable<T>: Comparable<T>{
           operator fun <T> Addable<T>.plus(a: T)
        }
        fun <T : Addable<T>> T.twiceTheLarger(a: T, b: T) {
            return if (a > b) a.plus(a) else b + b
        }
    

    【讨论】:

    • 如果我事先知道类型,那将是一个好方法。我在我的问题中添加了一段,澄清事实并非如此。
    • @DanielWolf 查看我的编辑和关于运营商的评论。
    • 恐怕你的函数不能编译,因为编译器不能保证每个实现Comparable&lt;T&gt;的类型也实现加号操作符。
    猜你喜欢
    • 2020-02-06
    • 2015-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-17
    • 1970-01-01
    • 1970-01-01
    • 2011-08-20
    相关资源
    最近更新 更多