Kotlin 内联方法不可见,除非扩展 Class
Kotlin inline Method is not Visible Unless Extending the Class
我 运行 在我为零垃圾收集编写的库中遇到了一个问题。我写了一个 myFunction
函数,但我有一个问题,我无法调用该函数,除非我扩展 class (在这种情况下) RandomClass
package com.charlatano
fun main(args: Array<String>) {
val hello = RandomClass<String>()
hello.myFunction { // Unresolved reference: myFunction
}
}
class myClass {
private val list = RandomClass<String>()
fun loop() {
list.myFunction { // Unresolved reference: myFunction
}
}
}
class myClassInherit : RandomClass<String>() {
private val list = RandomClass<String>()
fun loop() {
list.myFunction { // Compiles without issue
}
}
}
open class RandomClass<out E>() {
fun iterator(): Iterator<E> {
TODO()
}
inline fun <E> RandomClass<E>.myFunction(action: (E) -> Unit): Unit {
for (e in iterator()) action(e)
}
}
这是错误:
Error:(23, 8) Kotlin: Unresolved reference: myFunction
问题是您在 RandomClass
的不同接收器中为 RandomClass
的某个实例编写了扩展函数。因此它只能与 RandomClass
一起使用,其中 RandomClass
的实例 this
可以与显式或隐式接收者一起推断出来。在 Kotlin 中无法同时指定 class 的实例和不同的接收者。指定一个就可以,另一个可以隐含。
如果我们模拟一下,问题可能会更明显:
class A {
inline fun B.foo() { ... }
}
A().foo() <--- nope, need B().foo() within A()
B().foo() <--- nope, can't see B.foo() from outside A instance (scoped extension)
A::B.foo() <--- doesn't exist as syntax, I made this up
如何同时指定 A
和 B
? "Instance A receiver B call foo()" 没有语法。
但如果您已经在 A
内,例如:
class A {
inline fun B.foo() { ... }
fun bar() { B().foo() } <-- all good! We have A, we have B, and can call foo
}
A
的实例由 class 本身满足,而接收者则由 Foo
之前创建的 B
的新实例调用。与您的代码唯一不同的是,您调用 A
实例和 B
接收器是同一件事,但它们是进行此类函数调用需要知道的两个参数。
在你的情况下,你有两个简单的选择来摆脱对实例和接收器的需要:
1.不要使 myFunction
成为扩展函数,只使其内联:
open class RandomClass<out E>() {
fun iterator(): Iterator<E> {
TODO()
}
inline fun myFunction(action: (E) -> Unit): Unit {
for (e in iterator()) action(e)
}
}
2。将内联扩展移到 class 之外,这样它就不需要实例了:
open class RandomClass<out E>() {
fun iterator(): Iterator<E> {
TODO()
}
}
inline fun <E> RandomClass<E>.myFunction(action: (E) -> Unit): Unit {
for (e in iterator()) action(e)
}
不管怎样,你都没有编译器错误了。
class A {
inline fun B.foo() { ... }
}
foo
称为成员扩展函数,因为它是classA
的成员,是classB
的扩展。 foo
内部有两个接收器可用:
this@A
被调用为dispatch receiver,
this@foo
或简称 this
称为扩展接收器。
How can you specify both A and B at the same time? There is no syntax for "Instance A receiver B call foo()".
实际上有这样的语法,你只需要将A
作为隐式this
dispatch receiver:
with(A()) {
B().foo()
}
此处您将 A
的实例指定为隐式调度接收器,将 B
的实例指定为显式扩展接收器。
问题 classes 会是什么样子:
val randomClass = RandomClass<Any>()
val anotherRandomClass = RandomClass<Any>()
with(randomClass) {
// randomClass is both dispatch receiver and extension receiver
myFunction { }
// randomClass is dispatch receiver and anotherRandomClass is extension receiver
anotherRandomClass.myFunction { }
}
但是在你的情况下没有必要做 myFunction
成员扩展,因为它没有在内部使用两个接收器。正如 建议的那样,只需将其设为成员或扩展,而不是同时设为两者。
我 运行 在我为零垃圾收集编写的库中遇到了一个问题。我写了一个 myFunction
函数,但我有一个问题,我无法调用该函数,除非我扩展 class (在这种情况下) RandomClass
package com.charlatano
fun main(args: Array<String>) {
val hello = RandomClass<String>()
hello.myFunction { // Unresolved reference: myFunction
}
}
class myClass {
private val list = RandomClass<String>()
fun loop() {
list.myFunction { // Unresolved reference: myFunction
}
}
}
class myClassInherit : RandomClass<String>() {
private val list = RandomClass<String>()
fun loop() {
list.myFunction { // Compiles without issue
}
}
}
open class RandomClass<out E>() {
fun iterator(): Iterator<E> {
TODO()
}
inline fun <E> RandomClass<E>.myFunction(action: (E) -> Unit): Unit {
for (e in iterator()) action(e)
}
}
这是错误:
Error:(23, 8) Kotlin: Unresolved reference: myFunction
问题是您在 RandomClass
的不同接收器中为 RandomClass
的某个实例编写了扩展函数。因此它只能与 RandomClass
一起使用,其中 RandomClass
的实例 this
可以与显式或隐式接收者一起推断出来。在 Kotlin 中无法同时指定 class 的实例和不同的接收者。指定一个就可以,另一个可以隐含。
如果我们模拟一下,问题可能会更明显:
class A {
inline fun B.foo() { ... }
}
A().foo() <--- nope, need B().foo() within A()
B().foo() <--- nope, can't see B.foo() from outside A instance (scoped extension)
A::B.foo() <--- doesn't exist as syntax, I made this up
如何同时指定 A
和 B
? "Instance A receiver B call foo()" 没有语法。
但如果您已经在 A
内,例如:
class A {
inline fun B.foo() { ... }
fun bar() { B().foo() } <-- all good! We have A, we have B, and can call foo
}
A
的实例由 class 本身满足,而接收者则由 Foo
之前创建的 B
的新实例调用。与您的代码唯一不同的是,您调用 A
实例和 B
接收器是同一件事,但它们是进行此类函数调用需要知道的两个参数。
在你的情况下,你有两个简单的选择来摆脱对实例和接收器的需要:
1.不要使 myFunction
成为扩展函数,只使其内联:
open class RandomClass<out E>() {
fun iterator(): Iterator<E> {
TODO()
}
inline fun myFunction(action: (E) -> Unit): Unit {
for (e in iterator()) action(e)
}
}
2。将内联扩展移到 class 之外,这样它就不需要实例了:
open class RandomClass<out E>() {
fun iterator(): Iterator<E> {
TODO()
}
}
inline fun <E> RandomClass<E>.myFunction(action: (E) -> Unit): Unit {
for (e in iterator()) action(e)
}
不管怎样,你都没有编译器错误了。
class A {
inline fun B.foo() { ... }
}
foo
称为成员扩展函数,因为它是classA
的成员,是classB
的扩展。 foo
内部有两个接收器可用:
this@A
被调用为dispatch receiver,this@foo
或简称this
称为扩展接收器。
How can you specify both A and B at the same time? There is no syntax for "Instance A receiver B call foo()".
实际上有这样的语法,你只需要将A
作为隐式this
dispatch receiver:
with(A()) {
B().foo()
}
此处您将 A
的实例指定为隐式调度接收器,将 B
的实例指定为显式扩展接收器。
问题 classes 会是什么样子:
val randomClass = RandomClass<Any>()
val anotherRandomClass = RandomClass<Any>()
with(randomClass) {
// randomClass is both dispatch receiver and extension receiver
myFunction { }
// randomClass is dispatch receiver and anotherRandomClass is extension receiver
anotherRandomClass.myFunction { }
}
但是在你的情况下没有必要做 myFunction
成员扩展,因为它没有在内部使用两个接收器。正如