考虑:
class Foo {
fun CoroutineScope.foo() {
}
}
class Bar {
val f = Foo()
fun CoroutineScope.bar() { // this could also be "suspend fun bar = coroutineScope {"
f.foo() // unresolved reference
with (f) {
foo() // OK
}
with (f) {
with(this) {
foo() // OK
}
}
}
}
似乎在f.foo()
的首次尝试应该推断出CoroutineScope
上指定的bar()
接收者。似乎没有;但是为了更好地理解接收者,有人对为什么解释了吗?
修改
查看了some docs(特别是“将扩展声明为成员” )和Rene的回复之后,我尝试了一些其他操作:
import kotlinx.coroutines.*
class Foo {
fun CoroutineScope.foo() { println("Foo.foo")}
fun Baz.fed(){ println("Foo.fed") }
}
class Baz {
fun CoroutineScope.foo() { println("Baz.foo") }
fun Foo.fed(){ println("Baz.fed") }
}
fun CoroutineScope.foo() { println("CoroutineScope.foo") }
fun foo() { println("Global.foo") }
fun bar(scope: CoroutineScope) {
val f = Foo()
val b = Baz()
println ("Test 1")
foo() // foo() from Global
scope.foo() // foo() from CoroutineScope
//f.foo() // unresolved reference
println ("\nTest 2")
with(scope) {
foo() // foo() from CoroutineScope
//f.foo() // unresolved reference
}
println ("\nTest 3")
with(f) {
scope.foo() // foo() from Foo
foo() // foo() from Global
}
println ("\nTest 4")
with(scope) {
with (f) {
foo() // foo() from Foo
scope.foo() // foo() from Foo
}
}
println ("\nTest 5")
with(f) {
with (scope) {
foo() // foo() from Foo
scope.foo() // foo() from Foo
}
}
println ("\nTest 6")
with(b) {
with(f) {
with (scope) {
foo() // foo() from Foo
fed() // fed() from Baz
}
}
}
println ("\nTest 7")
with(f) {
with(b) {
with (scope) {
foo() // foo() from Baz
fed() // fed() from Foo
}
}
}
}
fun main() = runBlocking {
bar(this)
}
有趣的是,当两个上下文都通过with
可用时,它能够确定哪个是调度上下文,以及哪个扩展上下文,无论提供它们的顺序如何。但是,如果直接像f.bar()
那样指定扩展上下文,它将仅使用扩展接收器查找bar
的版本。 >类型Foo
或Foo
的直接成员(我仍然不清楚它如何查看 dispatch 和 extension 接收者在类定义中简单定义的函数)。因此似乎逻辑是这样的:
给出表达式x.y()
:
y()
x
c
,从最近添加的接收器开始,选择明确采用类型为调度接收器的第一个x.y()
c
-注意fun CoroutineScope.foo()
在全局范围内的行为就像没有派发接收器,因为测试6和7表明即使将scope
添加到可用的最后一个上下文列表,则使用Foo
的{{1}}(或Baz
)版本。给出表达式foo()
:
y()
。 (请注意:它首先选择最近添加的扩展接收器,然后尝试找到匹配的调度接收器(请参见测试6和7中的x.y()
)fed()
x
选择最近添加的上下文。
y()
x
选择最近添加的上下文
y()
的全局版本答案 0 :(得分:3)
您的声明:
class Foo {
fun CoroutineScope.foo() {
}
}
在类foo
的实例的上下文中定义CoroutineScope
的扩展函数Foo
。这意味着,如果您处于foo
类型为CoroutineScope
的范围内,则只能在this
的实例上调用Foo
。
第一次尝试f.foo()
的作用恰恰相反。您在foo()
的实例上调用Foo
,并且this
引用了CoroutineScope
。
另外两个示例使用with
将this
的引用设置为Foo
,因此您可以在外部foo
实例上调用CoroutineScope
。
顺便说一句:with(this)
毫无意义,因为this
将设置为this
。