You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin为Number类型函数实现嵌套infix扩展时类型不匹配问题

问题原因分析

为什么(Int) -> Int无法匹配(Number) -> Number

Kotlin的函数类型遵循形变规则:

  • 函数入参类型是逆变的:如果P1是P2的父类,那么(P2) -> R是(P1) -> R的父类
  • 函数返回值类型是协变的:如果R1是R2的子类,那么(P) -> R1是(P) -> R2的子类

对于(Int) -> Int和(Number) -> Number的匹配:

  1. 入参部分:Int是Number的子类,所以(Int) -> *是(Number) -> *的父类,父类型无法直接赋值给子类型
  2. 即使返回值Int是Number的子类符合协变规则,入参部分的逆变规则不满足,所以编译器会直接抛出类型不匹配错误

如果强行把(Int)->Int转为(Number)->Number,会存在类型安全风险:后者允许传入任意Number子类(比如Float、Long),但前者只能处理Int类型参数,运行时会抛出类型转换异常。

通用函数组合实现方案

使用泛型约束即可实现支持所有数字类型函数的nest中缀方法,同时保证类型安全:

class Entry {
    companion object {
        private fun f(x: Int) = x * 2
        private fun g(x: Int) = x + 2
        // 支持跨数字类型组合的示例函数
        private fun longF(x: Long) = x.toDouble() / 2
        private fun floatG(x: Float) = x.toLong() + 100L

        // 泛型nest实现,三个泛型分别对应组合后函数的入参、中间传递值、最终返回值
        private infix fun <A: Number, B: Number, C: Number> ((B) -> C).nest(inner: (A) -> B): (A) -> C {
            return { x -> this(inner(x)) }
        }

        @JvmStatic
        fun main(args: Array<String>) {
            // 同类型Int函数组合
            val intFunc = ::f nest ::g
            println(intFunc(10)) // 输出 24,逻辑和原始版本一致

            // 跨数字类型组合:Float -> Long -> Double
            val mixedFunc = ::longF nest ::floatG
            println(mixedFunc(8.8f)) // 输出 54.0
        }
    }
}

如果你不需要限定只能组合数字类型的函数,可以去掉泛型的: Number上界,该方法就可以支持任意类型的函数嵌套组合。

内容的提问来源于stack exchange,提问作者Langua

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 14:09:03