首页 > 解决方案 > kotlin 有按名称参数支持吗?

问题描述

Scala 具有按名称参数支持,其用法如下所示,是否可以在 kotlin 中实现这一点?

  def invoke(block: => Boolean) = block

  // usage
  var exposure = 0
  invoke(exposure == 1)

我在kotlin中有以下方法:

fun waitFor(condition: () -> Boolean) = condition()

// usage
var exposure = 0
waitFor { exposure == 1 }

waitFor(exposure == 1) // I want its usage to look like this, but it does not compile

waitFor是我们自定义 DSL 的一部分,它需要一个块,并且每次调用它时都需要对其进行评估。

标签: kotlin

解决方案


Kotlin 不支持按名称调用,但您可以使用委托属性模拟此功能(有限制),这些也可以在本地使用。

首先考虑 Kotlin 的惰性值。Kotlin 的惰性是通过委托属性实现的。惰性值在首次访问时进行评估,并且可以用作按名称调用,以防您只需要评估一次。

val exposure by lazy { 0 }
waitFor(exposure == 1)

您可以实现自定义委托属性,这将为您提供几乎按名称调用的语义

fun <T> callByName(block: () -> T) = object: ReadOnlyProperty<Any?, T> {
   override fun getValue(thisRef: Any?, property: KProperty<*>) = block()
}

像这样定义的变量或属性将在每次访问时使用提供的块进行评估,有点懒惰。这与按名称不同,因为变量在其范围内的块评估时仍会评估,这发生在方法调用之前waitFor

val exposure by callByName { UUID.randomUUID() }
val alwaysFalse = exposure == exposure
waitFor(exposure == 1)

这在简单的情况下很有用,但在您希望按名称调用整个块的情况下则不然。


推荐阅读