Метод Kotlin inline не видим, если не расширять класс

Я столкнулся с проблемой в библиотеке, которую я пишу для коллекций нулевого мусора. Я написал функцию myFunction но у меня есть проблема, когда я НЕ могу вызвать функцию, если я не RandomClass класс (в данном случае) 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 могут быть выведены вместе с явным или подразумеваемым приемником. В 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 одновременно? Синтаксиса «Экземпляр 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 } 

    Экземпляр для A выполняется самим классом, а приемник – новым экземпляром B , созданным до Foo . Единственный отличие от вашего кода заключается в том, что вы вызвали экземпляр и 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) } 

    В любом случае, у вас больше нет ошибок компилятора.

     class A { inline fun B.foo() { ... } } 

    foo называется функцией расширения члена, поскольку она является членом класса A и расширением для класса B Внутри foo доступны два приемника:

    • this@A называется приемником отправки,
    • this@foo или просто this называется расширением приемника.

    Как вы можете указать как A, так и B одновременно? Синтаксиса «Экземпляр A приемника B вызывать foo ()» отсутствует.

    На самом деле есть такой синтаксис, вам просто нужно иметь 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 , потому что он не использует два приемника внутри. Просто сделайте это либо членом, либо расширением, а не обоими, как предполагает этот ответ .

    Intereting Posts
    Как предотвратить закрытие диалогового окна (предупреждения) при касании снаружи или отменить использование Anko Gradle не будет импортировать зависимость bintray, но не вызывает никакой ошибки как вы получаете Idlingresource для работы в Kotlin с сопрограммами Как я могу заставить конечную точку остального читать файл cookie и использовать это значение в okhttp Interceptor? Kotlin Dokka – Не удается найти задачу Dokka в андроид-студии Будет ли карта Kotlin mapTo () перезаписывать данные уже в массиве? Две параллельные строки заменяются в строке kotlin Переменная Assert не Null Должен ли я использовать демо-код ARCore или написать его самостоятельно? Ввод общей лямбды в карту Связанные вызовы и наследование Почему выражения лямбда ведут себя по-разному для классов Kotlin и Java? Есть ли способ отфильтровать null Any? ценностей на карте Котлина? Kotlin: получить суперкласс из объекта класса – ошибка вывода объекта Доступ к R.drawable в Android Studio вызывает исключение KotlinFrontEndException