Kotlin重载invoke操作符的使用场景是什么?

pn9klfpd  于 2023-02-13  发布在  Kotlin
关注(0)|答案(1)|浏览(318)

为什么不使用顶级函数而重载调用操作符?重载调用操作符有什么好处吗?

class GetFollowableTopicsUseCase @Inject constructor(
    private val topicsRepository: TopicsRepository,
    private val userDataRepository: UserDataRepository
) {

  operator fun invoke(sortBy: TopicSortField = NONE): Flow<List<FollowableTopic>> 
  ...

}
bweufnob

bweufnob1#

有一个老的pair of sayings在像这样的编程社区中流传。
闭包是穷人的对象,对象是穷人的闭包。
事实上,在一种足够现代的语言中,比如Kotlin语(或者像我们现在使用的大多数语言一样),对象和闭包非常相似。你可以用它们所关闭的一堆函数和可变变量来替换Kotlin程序中的每一个类。同样,你可以用一个invoke函数的对象来替换程序中的每个函数,但是前者将是一场与类型系统的不断角力,而后者将是荒谬的冗长。
所以Kotlin让我们两个都做。你应该用哪一个?函数的优点是它们简短、敏捷、切中要害。而且,至少对函数程序员来说,函数通常应该没有副作用。另一方面,对象又吵又冗长。这是一件坏事,因为在浏览代码时需要更长的时间来阅读和理解。但这也是一件好事,因为它阻止你隐藏复杂性。
因此,如果你的函数很简单,就使用函数。如果它很复杂或者有状态,就使用命名对象,并且像任何公共类一样记录它。作为几个例子,下面是我将如何处理一些不同的情况。

  • 将两个数字相加的函数是简单的、无副作用的、引用透明的。
  • 一个向局部变量val添加一个数字的函数仍然非常简单。它是一个闭包,但是val是不可变的,所以函数的行为是可预测的。使用一个对象可能会有些过头,所以把它变成一个函数。
  • 一个跟踪它被调用了多少次并且每次都打印出那个数字的函数有副作用和局部状态。虽然它 * 可以 * 被写成一个围绕var的花哨闭包,但最好把它写成一个真实的对象,它的计数器变量是一个真正的示例变量,这样任何阅读代码的人都可以一眼看出发生了什么。

相关问题