Kotlin泛型乘法兼容问题:如何适配Int/Float/Long/Double
解决泛型数字乘积函数的实现问题
因为Kotlin的Number是抽象基类,并没有定义加减乘除等运算方法,所以直接用<T: Number>约束无法直接进行acc * number这类操作。下面提供几种可行的实现方案:
方案一:基于类型判断的直接实现
这种方法通过判断列表中元素的具体类型,转换为对应类型后执行乘积运算,最后转回泛型类型。适合元素类型统一的场景:
private fun <T : Number> productNumbers(listOfNumbers: List<T>, ignoreIndex: Int): T { return when (val first = listOfNumbers.firstOrNull()) { is Int -> listOfNumbers .filterIndexed { idx, _ -> idx != ignoreIndex } .map { it as Int } .fold(1) { acc, num -> acc * num } as T is Float -> listOfNumbers .filterIndexed { idx, _ -> idx != ignoreIndex } .map { it as Float } .fold(1f) { acc, num -> acc * num } as T is Long -> listOfNumbers .filterIndexed { idx, _ -> idx != ignoreIndex } .map { it as Long } .fold(1L) { acc, num -> acc * num } as T is Double -> listOfNumbers .filterIndexed { idx, _ -> idx != ignoreIndex } .map { it as Double } .fold(1.0) { acc, num -> acc * num } as T else -> throw IllegalArgumentException("不支持的数字类型: ${first?.javaClass?.simpleName}") } }
方案二:使用内联泛型+具体化类型(更可靠)
利用Kotlin的reified关键字在编译期获取泛型类型信息,无需依赖列表第一个元素判断类型,类型安全性更高:
inline fun <reified T : Number> productNumbers(listOfNumbers: List<T>, ignoreIndex: Int): T { val initialValue = when (T::class) { Int::class -> 1 as T Float::class -> 1f as T Long::class -> 1L as T Double::class -> 1.0 as T else -> throw IllegalArgumentException("不支持的数字类型: ${T::class.simpleName}") } return listOfNumbers.foldIndexed(initialValue) { index, acc, num -> if (index != ignoreIndex) { when (T::class) { Int::class -> (acc as Int * num as Int) as T Float::class -> (acc as Float * num as Float) as T Long::class -> (acc as Long * num as Long) as T Double::class -> (acc as Double * num as Double) as T else -> throw IllegalArgumentException("不支持的数字类型") } } else { acc } } }
方案三:定义运算接口扩展(面向对象风格)
先定义一个支持乘法的接口,再给各数字类型扩展实现该接口,最后基于接口约束实现泛型函数:
// 定义乘法运算接口 interface Multipliable<T> { fun multiply(other: T): T } // 给各数字类型扩展实现乘法接口 fun Int.multiply(other: Int): Int = this * other fun Float.multiply(other: Float): Float = this * other fun Long.multiply(other: Long): Long = this * other fun Double.multiply(other: Double): Double = this * other // 泛型函数实现 private fun <T : Number> productNumbers(listOfNumbers: List<T>, ignoreIndex: Int): T { val initialValue = when (listOfNumbers.firstOrNull()) { is Int -> 1 as T is Float -> 1f as T is Long -> 1L as T is Double -> 1.0 as T else -> throw IllegalArgumentException("不支持的数字类型") } return listOfNumbers.foldIndexed(initialValue) { index, acc, num -> if (index != ignoreIndex) { when (acc) { is Int -> acc.multiply(num as Int) as T is Float -> acc.multiply(num as Float) as T is Long -> acc.multiply(num as Long) as T is Double -> acc.multiply(num as Double) as T else -> throw IllegalArgumentException("不支持的数字类型") } } else { acc } } }
注意事项
- 以上方案均假设输入列表中的元素类型统一,若存在混合类型的场景,需要额外处理类型兼容问题
- 原代码中
1 as T的写法会导致类型转换异常(比如T为Float时,Int无法直接转Float),所以必须根据具体类型提供对应初始值
内容的提问来源于stack exchange,提问作者ant2009
相关产品推荐
相关产品推荐

