如何为多个无继承关系的类添加方法并减少重复代码?
如何为多个类添加重复功能并减少代码冗余?
当然有办法啦!你现在的写法确实存在重复代码,在Kotlin里我们有几种简洁的方式来解决这个问题,针对你给的Iterable和Sequence的例子,我给你推荐几个实用方案:
方案1:提取公共逻辑到独立函数
这是最直接的解决方案——把重复的统计逻辑抽成一个私有函数,然后让两个扩展函数都调用它,这样只需要维护一份核心逻辑:
/** 统计每个不同元素的出现次数。 */ fun <T> Iterable<T>.c() = countOccurrences(this) /** 统计每个不同元素的出现次数。 */ fun <T> Sequence<T>.c() = countOccurrences(this.asIterable()) // 私有核心逻辑,只需要维护这一份 private fun <T> countOccurrences(elements: Iterable<T>) = elements.groupingBy { it }.eachCount()
这种方式的好处是:
- 完全消除代码重复,核心逻辑只写一次
- 扩展函数保持简洁,只做类型转换和转发
- 私有函数不会对外暴露,不污染公共API
方案2:利用泛型约束(适用于有共同行为的类型)
如果你的目标类型有共同的行为或父类型,可以用泛型约束来统一扩展。不过注意,Sequence和Iterable没有直接的继承关系,所以这个方案不适合你的当前例子,但可以给你参考其他场景的用法:
比如,如果想给所有实现Iterable的类型添加这个方法,可以这么写:
fun <T, C> C.c() where C : Iterable<T> = groupingBy { it }.eachCount()
这样所有实现了Iterable的类(比如List、Set等)都会自动拥有这个c()方法,不需要单独写扩展。
方案3:扩展接口+委托(适用于自定义类)
如果是你自己定义的类,还可以通过扩展接口的方式统一添加功能。比如先定义一个包含统计方法的接口,然后让你的类实现这个接口,或者用委托模式:
interface Countable<T> { fun c(): Map<T, Int> } // 给Iterable扩展这个接口 fun <T> Iterable<T>.asCountable() = object : Countable<T> { override fun c() = groupingBy { it }.eachCount() } // 使用的时候 val list = listOf(1,2,2,3) list.asCountable().c()
不过这个方案对于系统类(比如Iterable、Sequence)来说有点繁琐,不如方案1直接。
总结一下,针对你当前的场景,方案1是最优选择,既能消除重复代码,又保持代码的清晰和简洁。
内容的提问来源于stack exchange,提问作者jrtapsell
相关产品推荐
相关产品推荐

