我已阅读 this question但我对 crossinline
关键字有一个更基本的问题。我不太确定它正在解决什么问题以及它是如何解决的。
来自 the Kotlin Docs ,
Note that some inline functions may call the lambdas passed to them as parameters not directly from the function body, but from another execution context, such as a local object or a nested function. In such cases, non-local control flow is also not allowed in the lambdas. To indicate that, the lambda parameter needs to be marked with the crossinline modifier:
[强调添加]
这句话对我来说是模棱两可的。首先,我很难想象“这种情况”是什么意思。我对问题所在有一个大致的了解,但无法举出一个很好的例子。
其次,短语“表明这一点”可以有多种读法。表明什么?那特殊情况是不允许的?它是允许的吗?给定函数定义中的非本地控制流是否允许(或不允许)?
简而言之,我很难弄清楚使用 this 的真正上下文是什么,使用它与客户交流什么,以及应用这个关键字的预期结果是什么。
最佳答案
First, I am having trouble actually picturing what is meant by "such cases". I have a general idea of what the issue is but can't come up with a good example of it.
这是一个例子:
interface SomeInterface {
fun someFunction(): Unit
}
inline fun someInterfaceBy(f: () -> Unit): SomeInterface {
return object : SomeInterface {
override fun someFunction() = f()
// ^^^
// Error: Can't inline 'f' here: it may contain non-local returns.
// Add 'crossinline' modifier to parameter declaration 'f'.
}
}
这里,传递给 someInterfaceBy { ... }
的函数被内联在实现 SomeInterface
的匿名类中。 someInterfaceBy
的每个调用站点的编译都会生成一个新类,该类具有不同的 someFunction()
实现。
要查看可能出现的问题,请考虑调用 someInterfaceBy { ... }
:
fun foo() {
val i = someInterfaceBy { return }
// do something with `i`
}
在内联 lambda 中,return
is non-local实际上意味着从foo
返回。但是由于没有调用 lambda 并泄漏到对象 i
中,return from foo
可能绝对没有意义:如果 i.在
(因此是 lambda)?foo
已经返回或什至在不同的线程中调用 someFunction()
一般来说,'这样的情况' 是指 inline
函数,这些函数不是在它们自己的主体(实际上,即考虑其他内联函数)中而是在一些内部调用它们的函数参数他们声明的其他函数,例如在非内联 lambda 和匿名对象中。
Second, the phrase "To indicate that," can be read multiple ways. To indicate what? That a particular case is not allowed? That it is allowed? That non-local control flow in a given function definition is (or is not) allowed?
这正是我上面描述的问题在 Kotlin 语言设计中得到解决的方式:每当 inline
函数打算将其函数参数内联到某个无法就地调用的地方 但存储后调用,inline
函数的参数应该标记为crossinline
,表示在传递的lambda中不允许非本地控制流在这里。
关于Kotlin 的 crossinline 关键字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45760817/