Я нашел интересную вещь, но я не мог этого сделать. Есть ли способ сделать локальный метод расширения доступным в функции с приемником.
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
должен быть создан кулаком. Таким образом, независимо от того, что вы делаете, до тех пор, пока вы используете локальную функцию, в принципе нет смысла избегать введения класса-оболочки. Ваше второе решение хорошо, и просто используйте его. Это и элегантно, и достаточно эффективно.
Если вы действительно не хотите добавлять создание класса / объекта, переместите эти функции расширения в область пакета и позвольте клиентам импортировать их.