如何编写适配所有Collection子类且参数类型正确的泛型函数?
修正Kotlin泛型函数的类型校验问题
原代码的核心问题是泛型推断逻辑宽松:编译器会自动把T推断为所有相关类型的共同父类(比如Int和String的共同父类是Any),导致本该拦截的类型不匹配场景被放行。我们可以通过调整泛型约束、优化集合处理逻辑来解决这个问题:
修正后的代码
inline fun <reified T, C : Collection<T>> C.dropElements(word: T): C { return when (this) { is MutableSet<*> -> (this.apply { remove(word) }) as C is Set<*> -> (this - word) as C is MutableList<*> -> (this.apply { removeIf { it == word } }) as C is List<*> -> filter { it != word } as C else -> throw UnsupportedOperationException("不支持该Collection子类") } } fun main() { val originalList: List<String> = readln().split(" ") val originalSet: Set<String> = originalList.toSet() val word: String = readln() val dropElements1: List<String> = originalList.dropElements(word).also(::println) val dropElements2: Set<String> = originalSet.dropElements(word).also(::println) // 此处会编译报错(符合预期):类型不匹配,String无法传入元素类型为Int的集合 // val dropElements3: List<Int> = listOf(1, 2, 3).dropElements(word).also(::println) }
关键修正细节
- 收紧泛型约束:把
reified T放在泛型参数首位,同时明确C必须是Collection<T>的子类。这样编译器会强制要求传入的word类型和集合元素类型严格一致,无法再推断出宽泛的Any类型,非法类型传入会直接触发编译错误。 - 补充可变集合支持:原代码只处理了不可变的
Set和List,新增MutableSet、MutableList的处理逻辑,避免可变集合类型转换时出现异常。 - 优化错误提示:将通用
Exception替换为语义更准确的UnsupportedOperationException,便于排查问题。
内容的提问来源于stack exchange,提问作者Kaloyan Karaivanov
相关产品推荐
相关产品推荐

