我在为零垃圾收集编写的库中遇到问题。我已经写了myFunction
函数,但是有一个问题,除非扩展类(在这种情况下)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
一起使用,在this
中,可以与显式或隐式接收器一起推断RandomClass
的实例A
。 Kotlin中无法同时指定类的实例和不同的接收者。仅当您指定一个且可以暗示另一个时,才可以这样做。
如果我们模拟它,问题可能会更加明显:
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
如何同时指定
B
和A
? “实例A接收者B调用foo()”没有语法。但是,如果您已经在
A
中,例如:class A {
inline fun B.foo() { ... }
fun bar() { B().foo() } <-- all good! We have A, we have B, and can call foo
}
类本身满足
B
的实例,而在调用Foo
之前创建的A
的新实例满足接收者的要求。与您的代码唯一不同的是,您将B
实例和myFunction
接收器称为同一对象,但是它们是调用此类型函数所需的两个参数。在您的情况下,您有两个简单的选择可以摆脱对实例和接收者的需求:
1.不要将ojit_code用作扩展功能,而只能使其内联:
open class RandomClass<out E>() {
fun iterator(): Iterator<E> {
TODO()
}
inline fun myFunction(action: (E) -> Unit): Unit {
for (e in iterator()) action(e)
}
}
2.将内联扩展名移到类之外,因此它也不需要实例:
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)
}
无论哪种方式,您都不会再出现编译器错误。