如何使用 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()
并使用 Long
s.
进行所有算术运算
例如:
fun <T> someFunction(a: T,b: T) {
Log.d(TAG, "${a.toLong() + b.toLong()}")
}
但这不是一个好的通用解决方案,因为通常没有“最佳”类型——无论您选择哪种类型,都有一些值无法存储。 (Long
是最大的整数类型,但不能存储小数。而 Double
是最大的浮点类型,但不能存储 Longs
的全精度——例如,Long.MAX_VALUE
和 Long.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。)
所以没有好的通用方法以通用方式处理数字。
相反,人们倾向于采用两种具体方法:
选择一个具体类型,然后使用它。‖通常,代码的要求决定了一个合适的类型(例如 Int
),并且虽然通用性很好,但通常并不是严格需要的。
提供一个Long
版本和一个Double
版本。‖在它们之间,这些类型可以包含所有可能的值内置数字类型,因此通常可以满足任何特定用途。
我想用 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()
并使用 Long
s.
例如:
fun <T> someFunction(a: T,b: T) {
Log.d(TAG, "${a.toLong() + b.toLong()}")
}
但这不是一个好的通用解决方案,因为通常没有“最佳”类型——无论您选择哪种类型,都有一些值无法存储。 (Long
是最大的整数类型,但不能存储小数。而 Double
是最大的浮点类型,但不能存储 Longs
的全精度——例如,Long.MAX_VALUE
和 Long.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。)
所以没有好的通用方法以通用方式处理数字。
相反,人们倾向于采用两种具体方法:
选择一个具体类型,然后使用它。‖通常,代码的要求决定了一个合适的类型(例如
Int
),并且虽然通用性很好,但通常并不是严格需要的。提供一个
Long
版本和一个Double
版本。‖在它们之间,这些类型可以包含所有可能的值内置数字类型,因此通常可以满足任何特定用途。