我发现了一件有趣的事情,但我无法做到。有没有办法在带接收器的函数中使本地扩展方法可用。
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();
}
答案 0 :(得分:0)
还没有这样的功能,我认为在不久的将来它也不会被添加。 您应该使用第二个版本。不要在乎添加包装类。实际上,避免引入包装类的想法是,只要您使用JVM后端,只需无意义,因为通过使用本地函数,您实际上是在添加本地类。
这是您的kotlin函数的等效Java代码,在您按照建议修复之后,假设您的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
的实例必须为拳头创造。所以,无论你做什么,只要你使用本地函数,基本上没有必要避免引入包装类。你的第二个解决方案是好的,只需使用它。它既优雅又高效。
如果您真的不想添加类/对象创建,请将这些扩展函数移动到包范围,然后让客户端导入它们。