如何在Kotlin中将布尔运算符作为参数传递以优化重复过滤逻辑代码?
问题:优化重复Kotlin函数,如何传递布尔运算符逻辑作为参数
我有两个函数,它们的核心逻辑几乎完全重复,唯一的区别是filter操作中的布尔判断(一个用==,一个用!=):
fun getMyListForFoo(): List<Blub> { //.. 大量代码行 return myRepo.queryList() .filter{ it.flag == Query.IS_FOO } .map{ //.. 映射逻辑 } }
另一个仅用于查询非Foo数据的函数:
fun getMyListForNotFoo(): List<Blub> { //.. 大量代码行 return myRepo.queryList() .filter{ it.flag != Query.IS_FOO } .map{ //.. 映射逻辑 } }
想知道有没有合适的Kotlin方式优化这段重复代码,同时想了解如何在Kotlin中将布尔运算符相关的逻辑作为参数传递。
回答
当然有简洁的优化方式!Kotlin的函数类型参数正好能解决这个问题——我们不需要直接传递布尔运算符本身(毕竟运算符是语法层面的元素),而是传递包含运算符判断的逻辑块,把重复的代码提取到一个通用函数里。
步骤1:提取通用的私有函数
先把两个函数里重复的代码(包括查询、映射逻辑,还有那一大段前置代码)抽出来,写一个私有函数,接收一个(Blub) -> Boolean类型的参数——这个参数就是我们的判断条件(谓词):
private fun getFilteredMyList(predicate: (Blub) -> Boolean): List<Blub> { //.. 这里放原来两个函数里的大量重复代码,只写一次! return myRepo.queryList() .filter(predicate) // 这里用传入的判断逻辑 .map{ //.. 原来的映射逻辑,只写一次! } }
步骤2:简化原有的两个公共函数
现在原来的两个函数只需要调用这个通用函数,传入各自的判断逻辑即可:
fun getMyListForFoo(): List<Blub> { return getFilteredMyList { it.flag == Query.IS_FOO } } fun getMyListForNotFoo(): List<Blub> { return getFilteredMyList { it.flag != Query.IS_FOO } }
进阶优化:提取可复用的判断逻辑
如果这些判断逻辑在其他地方也会用到,还可以把它们单独提取成变量或者函数,让代码更清晰:
// 把判断逻辑封装成可复用的函数类型变量 private val isFoo: (Blub) -> Boolean = { it.flag == Query.IS_FOO } private val isNotFoo: (Blub) -> Boolean = { it.flag != Query.IS_FOO } // 然后公共函数可以直接引用这些变量 fun getMyListForFoo(): List<Blub> { return getFilteredMyList(isFoo) } fun getMyListForNotFoo(): List<Blub> { return getFilteredMyList(isNotFoo) }
关于“传递布尔运算符”的说明
在Kotlin里,我们不能直接把==或者!=这样的运算符作为参数传递,因为它们本质是编译器处理的语法糖(对应equals()方法或者取反的equals())。但我们可以通过lambda表达式或者函数引用的方式,把使用运算符的判断逻辑封装成函数类型参数,这就是Kotlin中传递这类逻辑的标准方式。
这样优化后,重复代码完全消除,后续如果需要修改查询或映射逻辑,只需要修改通用函数即可,维护性大大提升!
内容的提问来源于stack exchange,提问作者Ralf Wickum
相关产品推荐
相关产品推荐

