如何使用 kotlin 在函数中添加两个数字类型的值?

How can I add two values with numeric type in function with kotlin?

我想用 Generic 求和 2 Int 或 2 Double。

fun <T> someFunction(a: T,b: T) {
    Log.d(TAG, "${a+b}") 
}

我认为这可能适合你

fun <T: Number> someFunction(a: T,b: T) {
    val result =  (a.toDouble()+b.toDouble()) as T
    Log.d(TAG, "$result")
}

或者如果你想return它

fun <T: Number> someFunction(a: T,b: T): T {
    return (a.toDouble()+b.toDouble()) as T
}
inline fun <reified T : Number> someFunction(a: T, b: T): T? {
  return when {
    a is Int && b is Int       -> (a.toInt() + b.toInt()) as T
    a is Double && b is Double -> (a.toDouble() + b.toDouble()) as T
    else                       -> null
  }
}

val resultInt = someFunction(2, 3)           // value: 5   , type: Int?
val resultDouble = someFunction(2.25, 3.5)   // value: 5.75, type: Double?
val resultMixed = someFunction(2, 3.5)       // value: null, type: Number?

不幸的是,没有好的方法来做到这一点。

虽然 Number 是数字类型的超class,但未指定 — 它让你做的只是 convert 值之一标准数字类型。它提供任何方法来进行算术或其他数字运算。

(这可能是因为类型不起作用。在具有许多数字类型的传统语言中,例如 C 和 Java,运算结果的类型取决于两种操作数类型: 添加一个 short 和一个 int 得到一个 int 结果。但是对于 class 方法没有办法表达它。)

因此,如果您想处理任何 Number,您可能可以采用两种方法。

由于 Number 提供的唯一功能是将其转换为特定的数字类型,一种方法是转换为“最佳”类型,然后在该类型中进行计算。例如,如果您只关心整数值,那么您可以调用 toLong() 并使用 Longs.

进行所有算术运算

例如:

fun <T> someFunction(a: T,b: T) {
    Log.d(TAG, "${a.toLong() + b.toLong()}")
}

但这不是一个好的通用解决方案,因为通常没有“最佳”类型——无论您选择哪种类型,都有一些值无法存储。 (Long 是最大的整数类型,但不能存储小数。而 Double 是最大的浮点类型,但不能存储 Longs 的全精度——例如,Long.MAX_VALUELong.MAX-VALUE - 1 都转换为相同的 Double 值。)‖因此,无论您选择哪种类型,都会存在某种形式的不精确或舍入风险。

另一种方法是查看您有哪些具体类型,并分别处理每个组合。‖例如:

例如:

fun <T> someFunction(a: T,b: T) {
    if ((a is Long && (b is Long || b is Int || b is Char || b is Short || b is Byte))
    || (b is Long && (a is Long || a is Int || a is Char || a is Short || a is Byte)))
        Log.d(TAG, "${a.toLong() + b.toLong()}")
    else if ((a is Int && (b is Int || b is Char || b is Short || b is Byte))
    || (b is Int && (a is Int || a is Char || a is Short || a is Byte)))
        Log.d(TAG, "${a.toInt() + b.toInt()}")
    else if ((a is Short && (b is Short || b is Byte))
    || (b is Short && (a is Short || a is Byte)))
        Log.d(TAG, "${a.toShort() + b.toShort()}")
    // …and so on, for all the other combinations you want to handle…
}

这给了你更好的控制;但它很少被使用,因为它在大多数情况下过于冗长和笨拙。 (而且它无法处理人们编写的 Number 的任何新子 classes。)

所以没有好的通用方法以通用方式处理数字。

相反,人们倾向于采用两种具体方法:

  1. 选择一个具体类型,然后使用它。‖通常,代码的要求决定了一个合适的类型(例如 Int),并且虽然通用性很好,但通常并不是严格需要的。

  2. 提供一个Long版本和一个Double版本。‖在它们之间,这些类型可以包含所有可能的值内置数字类型,因此通常可以满足任何特定用途。