我在为零垃圾收集编写的库中遇到问题。我已经写了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

如何同时指定BA? “实例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)
}

无论哪种方式,您都不会再出现编译器错误。

10-05 23:27