我在库中遇到了一个问题,我写的是零垃圾收集。我写了一个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
答案 0 :(得分:3)
问题是您在RandomClass
的不同接收者中为RandomClass
的某个实例编写了扩展函数。因此,它只能与RandomClass
一起使用,其中this
的实例RandomClass
可以与显式或隐含的接收者一起推断。 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
如何同时指定A
和B
? &#34;实例A接收器B没有语法调用foo()&#34;。
但如果您已经在A
内,例如:
class A {
inline fun B.foo() { ... }
fun bar() { B().foo() } <-- all good! We have A, we have B, and can call foo
}
A
的实例由类本身满足,接收者在调用B
之前创建Foo
的新实例。与您的代码唯一不同的是您调用了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。将内联扩展移到类外,这样它就不需要实例:
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)
}
无论哪种方式,您都不再有编译错误。
答案 1 :(得分:0)
class A {
inline fun B.foo() { ... }
}
foo
被称为成员扩展函数,因为它是类A
的成员和类B
的扩展。 foo
内部有两个接收器:
this@A
称为调度接收器,this@foo
或简称this
称为扩展接收方。如何同时指定A和B? &#34;实例A接收器B没有语法调用foo()&#34;。
实际上有这样的语法,你只需要A
作为隐式this
调度接收器:
with(A()) {
B().foo()
}
这里有A
实例指定为隐式调度接收器,B
实例作为显式扩展接收器。
对于来自问题的类,它会是什么样子:
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
成员扩展,因为它内部没有使用两个接收器。只需将其设为成员或扩展名,而不是两者,如this answer所示。