Kotlin 语言中泛型的扩展函数
在 Kotlin 中,我们可以为泛型类型(包括具体的泛型类和泛型参数)定义扩展函数,这提供了极大的灵活性。
1. 为泛型类定义扩展函数
基本语法
kotlin
// 为 List<T> 定义扩展函数
fun <T> List<T>.customFilter(predicate: (T) -> Boolean): List<T> {
return this.filter(predicate)
}
// 为 MutableList<T> 定义扩展函数
fun <T> MutableList<T>.removeIf(predicate: (T) -> Boolean): Boolean {
val iterator = this.iterator()
var removed = false
while (iterator.hasNext()) {
if (predicate(iterator.next())) {
iterator.remove()
removed = true
}
}
return removed
}
// 使用
val numbers = listOf(1, 2, 3, 4, 5)
val evens = numbers.customFilter { it % 2 == 0 } // [2, 4]
2. 带有类型约束的泛型扩展函数
使用上界约束
kotlin
// 只有实现了 Comparable 的类型才能使用这个扩展
fun <T : Comparable<T>> List<T>.sortedDescending(): List<T> {
return this.sortedDescending()
}
// 多个约束
fun <T> List<T>.sumByIfNumber(selector: (T) -> Number): Double
where T : Any, T : Comparable<T> {
return this.sumOf { selector(it).toDouble() }
}
// 使用
val numbers = listOf(1, 2, 3)
println(numbers.sortedDescending()) // [3, 2, 1]
val items = listOf("a", "bb", "ccc")
// 错误:String 没有实现 Number 接口
// println(items.sumByIfNumber { it.length })
3. 协变(out)和逆变(in)的扩展函数
协变扩展函数
kotlin
// 为协变类型定义扩展函数
fun <T> List<out T>.safeFirstOrNull(): T? {
return this.firstOrNull()
}
// 使用协变参数
interface Producer<out T> {
fun produce(): T
}
fun <T> Producer<T>.produceMultiple(times: Int): List<T> {
return List(times) { this.produce() }
}
逆变扩展函数
kotlin
// 为逆变类型定义扩展函数
interface Consumer<in T> {
fun consume(item: T)
}
fun <T> Consumer<T>.consumeAll(items: List<T>) {
items.forEach { this.consume(it) }
}
4. reified 泛型扩展函数
结合 reified 关键字,可以在运行时访问泛型类型信息:
kotlin
// 检查集合中的所有元素都是指定类型
inline fun <reified T> List<*>.allOfType(): Boolean {
return this.all { it is T }
}
// 从 JSON 字符串解析为指定类型
inline fun <reified T> String.fromJson(): T? {
// 使用 Gson 或其他 JSON 库
return try {
// 假设有 gson 实例可用
gson.fromJson(this, T::class.java)
} catch (e: Exception) {
null
}
}
// 使用
val mixedList = listOf(1, 2, "3", 4)
println(mixedList.allOfType<Int>()) // false
val json = """{"name": "John", "age": 30}"""
val person = json.fromJson<Person>() // 自动推断类型
5. 为泛型对(Pair/Triple)定义扩展函数
kotlin
// 为 Pair 定义扩展函数
fun <A, B> Pair<A, B>.swap(): Pair<B, A> {
return Pair(second, first)
}
fun <A, B, C> Triple<A, B, C>.rotate(): Triple<C, A, B> {
return Triple(third, first, second)
}
// 为两个相同类型的 Pair 定义扩展函数
fun <T : Comparable<T>> Pair<T, T>.sorted(): Pair<T, T> {
return if (first <= second) this else swap()
}
// 使用
val pair = Pair("hello", 123)
val swapped = pair.swap() // Pair(123, "hello")
val numbers = Pair(5, 3)
val sorted = numbers.sorted() // Pair(3, 5)
6. 高阶泛型扩展函数
接受函数参数的泛型扩展
kotlin
// 为 Sequence<T> 定义扩展函数
fun <T, R> Sequence<T>.mapWithIndex(
transform: (index: Int, T) -> R
): Sequence<R> = sequence {
var index = 0
for (item in this@mapWithIndex) {
yield(transform(index++, item))
}
}
// 为 Iterable<T> 定义扩展函数
fun <T, K, V> Iterable<T>.associateByMany(
keySelector: (T) -> K,
valueTransform: (T) -> V
): Map<K, List<V>> {
val result = mutableMapOf<K, MutableList<V>>()
for (element in this) {
val key = keySelector(element)
val list = result.getOrPut(key) { mutableListOf() }
list.add(valueTransform(element))
}
return result
}
// 使用
val names = listOf("Alice", "Bob", "Charlie", "Alice")
val map = names.associateByMany(
keySelector = { it.first().uppercaseChar() },
valueTransform = { it.length }
)
// 结果: {'A': [5, 5], 'B': [3], 'C': [7]}
7. 泛型扩展属性
kotlin
// 泛型扩展属性
val <T> List<T>.midElement: T?
get() = if (isEmpty()) null else this[size / 2]
// 带有类型约束的泛型扩展属性
val <T : Comparable<T>> List<T>.isSorted: Boolean
get() = this.sorted() == this
// 可空泛型扩展属性
val <T> Collection<T>?.sizeOrZero: Int
get() = this?.size ?: 0
// 使用
val numbers = listOf(1, 2, 3, 4, 5)
println(numbers.midElement) // 3
println(numbers.isSorted) // true
val nullableList: List<Int>? = null
println(nullableList.sizeOrZero) // 0
8. 实际应用示例
网络请求处理
kotlin
// Retrofit 响应处理
sealed class ApiResult<out T> {
data class Success<T>(val data: T) : ApiResult<T>()
data class Error(val exception: Exception) : ApiResult<Nothing>()
}
// 为 ApiResult 定义扩展函数
fun <T> ApiResult<T>.onSuccess(block: (T) -> Unit): ApiResult<T> {
if (this is ApiResult.Success) {
block(this.data)
}
return this
}
fun <T> ApiResult<T>.onError(block: (Exception) -> Unit): ApiResult<T> {
if (this is ApiResult.Error) {
block(this.exception)
}
return this
}
// 映射结果
fun <T, R> ApiResult<T>.map(transform: (T) -> R): ApiResult<R> {
return when (this) {
is ApiResult.Success -> ApiResult.Success(transform(this.data))
is ApiResult.Error -> this
}
}
// 使用
apiService.getUser()
.onSuccess { user ->
updateUI(user)
}
.onError { error ->
showError(error)
}
集合处理工具
kotlin
// 安全转换集合类型
fun <T, R : Any> Iterable<T>.mapNotNull(
transform: (T) -> R?
): List<R> {
return this.mapNotNull(transform)
}
// 分组并排序
fun <T, K> List<T>.groupBySorted(
keySelector: (T) -> K,
sortKeys: Comparator<K>? = null
): Map<K, List<T>> {
val map = this.groupBy(keySelector)
return if (sortKeys != null) {
map.toSortedMap(sortKeys)
} else {
map
}
}
// 查找重复项
fun <T> Iterable<T>.findDuplicates(): Set<T> {
val seen = mutableSetOf<T>()
val duplicates = mutableSetOf<T>()
for (item in this) {
if (!seen.add(item)) {
duplicates.add(item)
}
}
return duplicates
}
// 使用
val items = listOf(1, 2, 2, 3, 3, 3, 4)
val duplicates = items.findDuplicates() // [2, 3]
9. DSL 构建中的泛型扩展
kotlin
// 构建类型安全的 DSL
class Table<out T> {
private val rows = mutableListOf<T>()
fun row(init: RowBuilder<T>.() -> Unit) {
val builder = RowBuilder<T>().apply(init)
rows.add(builder.build())
}
fun getRows(): List<T> = rows
}
class RowBuilder<T> {
var data: T? = null
fun build(): T {
return data ?: throw IllegalStateException("Row data not set")
}
}
// 泛型扩展函数来创建表
fun <T> createTable(init: Table<T>.() -> Unit): Table<T> {
return Table<T>().apply(init)
}
// 使用
data class Person(val name: String, val age: Int)
val table = createTable<Person> {
row {
data = Person("Alice", 30)
}
row {
data = Person("Bob", 25)
}
}
10. 约束类型参数的复杂场景
kotlin
// 多个约束和类型参数
interface Identifiable<ID> {
val id: ID
}
interface Timestamped {
val createdAt: Long
}
// T 必须同时实现 Identifiable 和 Timestamped
fun <T, ID> List<T>.findById(id: ID): T?
where T : Identifiable<ID>, T : Timestamped {
return this.find { it.id == id }
}
// 使用扩展函数进行排序
fun <T, ID> List<T>.sortByCreationTime(): List<T>
where T : Identifiable<ID>, T : Timestamped {
return this.sortedBy { it.createdAt }
}
11. 性能优化考虑
kotlin
// 内联泛型扩展函数以减少开销
inline fun <T, R> List<T>.mapInline(
crossinline transform: (T) -> R
): List<R> {
val result = ArrayList<R>(this.size)
for (item in this) {
result.add(transform(item))
}
return result
}
// 避免不必要的对象创建
fun <T> Iterable<T>.forEachIndexed(
action: (index: Int, T) -> Unit
) {
var index = 0
for (item in this) {
action(index++, item)
}
}
12. 与 Java 互操作
kotlin
// 为 Java 集合定义扩展函数
fun <T> java.util.ArrayList<T>.addIfNotNull(element: T?) {
element?.let { this.add(it) }
}
// 处理 Java 原始类型
fun <T> Array<T>.toImmutableList(): List<T> {
return this.toList()
}
// 使用注解改善互操作性
@JvmName("filterStrings")
fun List<String>.filterLongStrings(): List<String> {
return this.filter { it.length > 5 }
}
最佳实践总结
- 保持简洁:泛型扩展函数应该专注于单一职责
- 明确命名:名称应该清晰地表达函数的功能
- 合理约束:使用类型约束确保类型安全,但不要过度约束
- 考虑性能 :对于高频使用的函数,考虑使用
inline - 提供文档:复杂泛型扩展应该包含文档说明
- 避免冲突:确保扩展函数不会与现有函数冲突
- 测试覆盖:泛型扩展函数应该被充分测试
泛型扩展函数是 Kotlin 中非常强大的特性,它们可以帮助您创建更通用、更类型安全且更易用的 API。