Как сделать локальный метод расширения доступным в функции с приемником?

Я нашел интересную вещь, но я не мог этого сделать. Есть ли способ сделать локальный метод расширения доступным в функции с приемником.

val list = ArrayList<Any>(); fun <T> Array<T>.bind(context: MutableList<in T>, block: Array<T>.() -> Unit) { fun Array<T>.save() { context.addAll(this); } block(); } arrayOf(1, 2, 3).bind(list) { save(); //todo: how to bind extension in execution scope }; 

Я знаю, что есть альтернативный способ, вводя другой тип для получателя, но я хочу его избежать. например:

 interface Savable { fun save(); } fun <T> Array<T>.bind(context: MutableList<in T>, block: Savable.() -> Unit) { val proxy = object : Savable { override fun save() { context += this@bind; } }; proxy.block(); } 

Такой функции пока нет, и я думаю, что в ближайшем будущем она не будет добавлена. Вы должны просто использовать свою вторую версию. Не стоит добавлять класс оболочки . Идея избежать введения класса-оболочки на самом деле, если вы используете JVM-бэкэнд, просто вздор , потому что, используя локальную функцию, вы фактически добавляете локальный класс.

Это эквивалентный Java-код вашей функции kotlin после исправления, как вы предположили, с предположением, что ваша функция bind живет в файле bind.kt :

 public final class BindKt { public static <T> void bind(T[] receiver, List<? super T> context, Function1<T> block) { class Local { // the name of local class is unimportant, as it's generated by compiler. It should looks like "package.name.BindKt$bind$X" where X is a number. public void save(T[] receiver) { context.addAll(receiver); } } block.invoke(this); // this won't compile. Neither will yours. } } 

Как вы можете видеть, save НЕ компилируется в статический метод, а это значит, что если ваш block каким-то образом когда-либо называл это save , экземпляр Local должен быть создан кулаком. Таким образом, независимо от того, что вы делаете, до тех пор, пока вы используете локальную функцию, в принципе нет смысла избегать введения класса-оболочки. Ваше второе решение хорошо, и просто используйте его. Это и элегантно, и достаточно эффективно.

Если вы действительно не хотите добавлять создание класса / объекта, переместите эти функции расширения в область пакета и позвольте клиентам импортировать их.

Intereting Posts
Fatal Exception: java.lang.RuntimeException с библиотекой Klaxon json Kotlin Как проверить, что строка не равна строке, тогда она будет работать иначе? в котлин версия kotlin, которая используется для построения с градиентом (1.1.2-5), отличается от той, что включена в плагин IDE (1.1.2-4) Неопределенная ссылка в Android Studio 3 Canary Многопоточный рендеринг изображений в JavaFx / Kotlin Kotlin и @Transient Доступ к царству из неправильной нити в Espresso бесконечные последовательности kotlin с функцией итератора Почему «как» в Котлине не бросили в этом случае Есть ли способ войти в PayPal с помощью htmlunit? Получить коэффициенты чисел в Котлине Приложение Kotlin / Android – изменение элементов представления извне. Задержка с изменением размера дочерних элементов RecyclerView мой контроллер Spring-Boot (Kotlin) не работает, что возвращает String Внедрение типизированного класса, параметризованного абстрактным типом