在lambda文字上指定接收器,而无需类型推断

时间:2018-09-12 02:30:57

标签: kotlin

假设我想要一个类型为Foo.()->Unit的lambda表达式

很明显,我可以依靠类型推断来指定它,以便lambda捕获收件人类型:val myLambda: Foo.()->Unit = { ... }

我的直觉是我可以做类似的事情:val myLambda = Foo.{ ... }

但这似乎不起作用。似乎不依靠lhs的类型推断就无法表达特定类型的lambda值似乎很奇怪。

有我不知道的语法吗?

1 个答案:

答案 0 :(得分:0)

没有语法可以完全满足您的需求。正如已经进行了布局,您可以创建一个Foo作为其接收者的lambda,方法是在将其传递给采用此类lambda的函数时进行创建:

fun useFooExtension(fooExtension: Foo.() -> Unit) {
    fooExtension(Foo())
}

useFooExtension {
    println(this is Foo)
}

或者通过显式指定变量的类型,例如:

var foo1: Foo.() -> Unit = { println(this is Foo) }

但是,您可以 声明一个以Foo作为其第一个参数的lambda,并使用此显式lambda语法(变量类型仅在此处用于说明目的,否则是多余的,并且推断):

var foo2: (Foo) -> Unit = { foo: Foo -> println(foo is Foo) }

这两种类型的lambda实际上是可以交叉分配的,因为Foo上的扩展名实际上也只是将Foo作为其底层参数。因此,您可以做所有这些事情:

foo1 = foo2
foo2 = foo1

useFooExtension(foo1)
useFooExtension(foo2)

这两种类型之间有一个区别:如果要使用Foo实例调用它们,则只能将foo1作为扩展名使用,但是可以像调用它们一样调用它们两者将Foo作为他们的第一个参数。这些都是有效的呼叫:

Foo().foo1()

foo1(Foo())
foo2(Foo())