如何编写支持所有Number类型的Kotlin函数?现有求和代码无法运行
哈哈,这个问题我刚入门Kotlin的时候也踩过一模一样的坑!你写的代码报错的核心原因很简单:Number是所有数值类型的抽象父类,但它本身并没有重载+操作符。Kotlin里的Int、Double这些子类各自实现了+,但抽象的Number实例没办法直接做加法——编译器根本不知道该用哪种数值类型的加法逻辑。
下面给你几种不同场景下的解决方案:
方案1:统一转换为Double求和(最简单)
如果对精度要求不是极端严格,直接把所有Number转成Double是最省事的做法,因为所有数值类型都能安全转成Double:
fun sum(x: Number, y: Number): Double { return x.toDouble() + y.toDouble() } // 测试: println(sum(2.2, 2)) // 输出 4.2
这个方法的好处是代码极简,能处理所有Number子类的组合(比如Int+Double、Long+Float等),缺点是整数相加也会返回Double,可能不符合某些需要保留原类型的场景。
方案2:按类型匹配保留原类型(更灵活)
如果希望尽量保留原始数值类型(比如Int+Int返回Int,Double+Double返回Double),可以用when语句判断参数的具体类型:
fun sum(x: Number, y: Number): Number { return when { x is Int && y is Int -> x + y x is Long && y is Long -> x + y x is Float && y is Float -> x + y x is Double && y is Double -> x + y x is Short && y is Short -> x + y x is Byte && y is Byte -> x + y // 不同类型组合的情况,比如Int+Double,这里选择转成Double兜底 else -> x.toDouble() + y.toDouble() } } // 测试: println(sum(2, 3)) // 输出 5(Int类型) println(sum(2.2, 2.0)) // 输出 4.2(Double类型) println(sum(2.2, 2)) // 输出 4.2(Double类型)
这个方法能尽可能保留原类型的精度,同时处理不同类型组合的情况,适合对返回类型有要求的场景。
方案3:泛型+Reified类型(同类型参数约束)
如果你的场景中,两个参数总是同一种数值类型,可以用泛型配合reified关键字,让代码更优雅:
inline fun <reified T : Number> sum(x: T, y: T): Number { return when (T::class) { Int::class -> (x as Int) + (y as Int) Long::class -> (x as Long) + (y as Long) Double::class -> (x as Double) + (y as Double) // 其他类型按需添加 else -> x.toDouble() + y.toDouble() } } // 测试: println(sum(2, 3)) // 输出 5(Int) println(sum(2.2, 3.3)) // 输出 5.5(Double) // 注意:这个方法不支持不同类型参数,sum(2.2,2)会编译报错,因为2.2是Double,2是Int,类型不匹配
这种方式适合明确要求两个参数类型一致的场景,代码复用性更好。
再啰嗦一句为什么原代码不行
Kotlin的Number类只是定义了数值类型的通用接口(比如toInt()、toDouble()这些转换方法),但并没有定义plus(也就是+操作符对应的方法)。每个子类(比如Int)自己实现了plus方法,但抽象的Number实例无法确定该调用哪个子类的实现,所以编译器会直接报错。
内容的提问来源于stack exchange,提问作者Alex Craft

