Kotlin 中为超类定义扩展函数
在 Kotlin 中,您可以在超类(如 Any、Any?、Number 等)上定义扩展函数,这样所有继承该类的子类都能使用这些扩展。
1. 为 Any 类定义扩展函数
Any 是 Kotlin 中所有非空类型的根类,为它定义扩展函数意味着几乎所有对象都能使用:
// 为 Any 类定义扩展函数 - 所有非空对象都能使用
fun Any?.safeToString(): String {
return this?.toString() ?: "null"
}
fun Any.printType() {
println("对象类型: ${this::class.simpleName}")
println("对象哈希码: ${this.hashCode()}")
}
// 使用
val str: String? = null
println(str.safeToString()) // 输出: null
val number = 42
number.printType() // 输出: 对象类型: Int
val list = listOf(1, 2, 3)
list.printType() // 输出: 对象类型: ArrayList
2. 为 Any? 类定义扩展函数
Any? 是所有可空和非空类型的根类:
// 为 Any? 定义扩展函数 - 包括可空类型
fun Any?.isNotNullAnd(condition: (Any) -> Boolean): Boolean {
return this != null && condition(this)
}
fun Any?.ifNotNull(block: (Any) -> Unit) {
if (this != null) block(this)
}
// 使用
val value: Any? = "Hello"
val result = value.isNotNullAnd { it is String } // true
value.ifNotNull {
println("值存在: $it")
}
3. 为 Number 超类定义扩展函数
Number 是所有数值类型的超类(Int、Double、Float 等):
// 为 Number 定义扩展函数 - 所有数值类型都能使用
fun Number.toFormattedString(): String {
return when (this) {
is Int -> "整数: $this"
is Double -> "双精度: ${"%.2f".format(this)}"
is Float -> "浮点数: ${"%.1f".format(this)}"
else -> this.toString()
}
}
fun Number.square(): Number {
return when (this) {
is Int -> this * this
is Double -> this * this
is Float -> this * this
else -> throw UnsupportedOperationException("不支持的数值类型")
}
}
// 使用
val intValue: Number = 5
println(intValue.toFormattedString()) // 输出: 整数: 5
println(intValue.square()) // 输出: 25
val doubleValue: Number = 3.1415
println(doubleValue.toFormattedString()) // 输出: 双精度: 3.14
4. 为 CharSequence 超类定义扩展函数
CharSequence 是 String、StringBuilder、CharBuffer 等的超类:
// 为 CharSequence 定义扩展函数 - String、StringBuilder 等都能使用
fun CharSequence.containsIgnoreCase(other: CharSequence): Boolean {
return this.toString().contains(other.toString(), ignoreCase = true)
}
fun CharSequence.countWords(): Int {
return this.split("\\s+".toRegex()).count { it.isNotBlank() }
}
fun CharSequence.truncate(maxLength: Int): CharSequence {
return if (this.length <= maxLength) this
else this.subSequence(0, maxLength - 3) + "..."
}
// 使用
val string: CharSequence = "Hello World"
val builder: CharSequence = StringBuilder("Kotlin Programming")
println(string.containsIgnoreCase("WORLD")) // true
println(builder.countWords()) // 2
println(string.truncate(8)) // Hello...
5. 为 Comparable 超类定义扩展函数
// 为 Comparable 定义扩展函数
fun <T : Comparable<T>> T.isBetween(min: T, max: T): Boolean {
return this in min..max
}
fun <T : Comparable<T>> T.clamp(min: T, max: T): T {
return when {
this < min -> min
this > max -> max
else -> this
}
}
// 使用
val number = 15
println(number.isBetween(10, 20)) // true
println(25.clamp(0, 100)) // 25
println(150.clamp(0, 100)) // 100
6. 为 Collection 超类定义扩展函数
// 为 Collection 定义扩展函数
fun <T> Collection<T>.secondOrNull(): T? {
return this.elementAtOrNull(1)
}
fun <T> Collection<T>.isNotEmptyAnd(predicate: (Collection<T>) -> Boolean): Boolean {
return this.isNotEmpty() && predicate(this)
}
// 使用
val list = listOf(1, 2, 3, 4)
val set = setOf("A", "B", "C")
println(list.secondOrNull()) // 2
println(set.isNotEmptyAnd { it.size > 2 }) // true
7. 为自定义超类定义扩展函数
// 定义自定义超类
open class Shape(val name: String)
class Circle(name: String, val radius: Double) : Shape(name)
class Rectangle(name: String, val width: Double, val height: Double) : Shape(name)
// 为 Shape 超类定义扩展函数
fun Shape.getDescription(): String {
return "形状: $name"
}
// 这个扩展函数所有 Shape 的子类都能使用
fun Shape.printInfo() {
println(this.getDescription())
when (this) {
is Circle -> println("半径: $radius")
is Rectangle -> println("宽度: $width, 高度: $height")
else -> println("未知形状")
}
}
// 使用
val circle = Circle("圆形", 5.0)
val rectangle = Rectangle("矩形", 4.0, 6.0)
circle.printInfo()
// 输出:
// 形状: 圆形
// 半径: 5.0
rectangle.printInfo()
// 输出:
// 形状: 矩形
// 宽度: 4.0, 高度: 6.0
8. 使用类型参数约束定义超类扩展函数
// 使用上界约束定义泛型扩展函数
fun <T : Any> T?.orDefault(default: T): T {
return this ?: default
}
fun <T : CharSequence> T.ensurePrefix(prefix: String): T {
return if (this.startsWith(prefix)) this
else "$prefix$this" as T
}
// 使用
val nullableString: String? = null
println(nullableString.orDefault("默认值")) // 输出: 默认值
val path = "file.txt"
println(path.ensurePrefix("/")) // 输出: /file.txt
9. 实际项目应用示例
Android 开发中的应用
// 为 View 超类定义扩展
fun View.setVisible(isVisible: Boolean) {
this.visibility = if (isVisible) View.VISIBLE else View.GONE
}
fun View.setOnSingleClickListener(delay: Long = 500, onClick: (View) -> Unit) {
var lastClickTime = 0L
this.setOnClickListener {
val currentTime = System.currentTimeMillis()
if (currentTime - lastClickTime > delay) {
lastClickTime = currentTime
onClick(it)
}
}
}
// 使用 - 所有 View 子类都能使用
button.setVisible(true)
imageView.setOnSingleClickListener {
// 防止重复点击
}
响应式编程中的应用
// 为 Flow 超类定义扩展
fun <T> Flow<T>.throttleFirst(windowDuration: Long): Flow<T> = flow {
var lastEmissionTime = 0L
collect { value ->
val currentTime = System.currentTimeMillis()
if (currentTime - lastEmissionTime > windowDuration) {
lastEmissionTime = currentTime
emit(value)
}
}
}
fun <T> Flow<T>.debug(tag: String): Flow<T> = flow {
collect { value ->
println("[$tag] 接收到: $value")
emit(value)
}
}
10. 注意事项和最佳实践
注意事项
// 1. 扩展函数不会被子类重写
open class Animal
class Dog : Animal()
fun Animal.speak() = "Animal sound"
fun Dog.speak() = "Woof!"
fun main() {
val animal: Animal = Dog()
println(animal.speak()) // 输出: Animal sound (不是 Woof!)
}
// 2. 避免与现有成员函数冲突
// 如果扩展函数与成员函数签名相同,成员函数优先
class MyClass {
fun doSomething() = println("成员函数")
}
fun MyClass.doSomething() = println("扩展函数") // 不会被调用
// 3. 谨慎使用 Any 扩展
fun Any.customToString(): String {
return "自定义: ${this::class.simpleName}"
}
// 这会影响到所有对象,可能会造成混淆
最佳实践
// 1. 使用特定类型代替 Any,如果可能的话
// 不好:
fun Any?.safeToString(): String = this?.toString() ?: "null"
// 好:
fun CharSequence?.safeToString(): String = this?.toString() ?: ""
// 2. 为扩展函数提供清晰的命名空间
package com.example.extensions.any
fun Any?.debug(): String {
return "[${this?.javaClass?.simpleName}] $this"
}
// 3. 提供有用的默认值
fun Number?.orZero(): Number {
return this ?: 0
}
// 4. 考虑性能影响
// 避免在频繁调用的扩展函数中创建过多临时对象
11. 使用 reified 结合超类扩展
// 结合 reified 和超类扩展
inline fun <reified T : Any> Any?.castOrNull(): T? {
return this as? T
}
inline fun <reified T : Any> Any?.requireType(): T {
return this as T
}
// 使用
val anyValue: Any = "Hello, World"
val string: String? = anyValue.castOrNull() // 安全转换
val requiredString: String = anyValue.requireType() // 不安全转换,失败时抛异常
12. 扩展函数组合使用
// 创建工具函数链
fun Any?.ifNotNullThen(block: (Any) -> Unit): Any? {
this?.let(block)
return this
}
fun Any?.ifNullThen(block: () -> Unit): Any? {
if (this == null) block()
return this
}
// 使用 - 创建流畅的 API
val result = someNullableValue
.ifNotNullThen { println("值存在: $it") }
.ifNullThen { println("值为空") }
总结
为超类定义扩展函数是 Kotlin 中非常强大的特性,它允许您:
- 提供通用功能:为所有对象类型添加常用功能
- 减少重复代码:避免为每个子类重复定义相同功能
- 创建流畅 API:通过扩展函数链提供更好的开发体验
- 增强类型安全:通过泛型约束提供类型安全的扩展
但是需要注意:
- 扩展函数是静态解析的,不支持多态
- 优先考虑特定类型而非
Any - 避免与现有成员函数冲突
- 合理组织扩展函数的包结构
合理使用超类扩展函数可以显著提高代码的可读性和可维护性。