Kotlin中如何将具体化泛型函数设为可选实现同名重载
合并同名Kotlin工具函数的实现方案
原函数场景还原
假设你原本有两个功能一致但输入逻辑不同的工具函数,因JVM签名冲突无法直接同名:
// 直接收集SharedFlow的版本 fun <T> SharedFlow<T>.collect(collector: (T) -> Unit) { this.onEach(collector).launchIn(CoroutineScope(Dispatchers.Default)) } // 按子类型过滤后收集的版本(具体化类型参数) inline fun <reified K : T, T> SharedFlow<T>.collect(collector: (K) -> Unit) { this.filterIsInstance<K>().onEach(collector).launchIn(CoroutineScope(Dispatchers.Default)) }
合并实现方案
利用Kotlin的具体化类型参数和类型推断优先级,可以将两个逻辑合并为一个同名函数,无需重命名或传递Class参数:
inline fun <reified K : T, T> SharedFlow<T>.collect(collector: (K) -> Unit) { val targetFlow = when { K::class == T::class -> this as SharedFlow<K> else -> this.filterIsInstance<K>() } targetFlow.onEach(collector).launchIn(CoroutineScope(Dispatchers.Default)) }
使用方式
- 不指定类型参数:Kotlin会自动将
K推断为T,此时跳过过滤逻辑,等价于原直接收集版本val animalFlow: SharedFlow<Animal> = ... animalFlow.collect { animal -> // 处理所有Animal类型元素 } - 指定具体化类型参数:自动过滤出目标子类型,等价于原过滤收集版本
animalFlow.collect<Dog> { dog -> // 仅处理Dog类型元素 }
核心原理
- inline+reified参数:让编译器在编译期获取类型参数的实际类型信息,避免JVM层面的签名冲突(inline函数的类型逻辑会被内联到调用处,生成适配的字节码)
- 类型推断逻辑:当不显式指定
K时,编译器会将其推断为与T相同的类型,此时跳过过滤操作,保留原直接收集的性能和逻辑 - 类型判断:通过
K::class == T::class判断是否需要过滤,若需更严谨的泛型类型判断(如带参数的泛型),可改用typeOf<K>() == typeOf<T>()(需依赖kotlin-reflect)
内容的提问来源于stack exchange,提问作者Shadow
相关产品推荐
相关产品推荐

