反射调用函数并使用默认参数 [英] Reflectively calling function and using default parameters

查看:117
本文介绍了反射调用函数并使用默认参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

提供以下功能

fun function(x: Int = 12) {
    println("x = $x")
}

如何在不指定x的情况下使用反射调用它(或者以某种方式使用默认值,对其进行硬编码)?

How can I using reflection invoke it without specifying x (or somehow using default value, not hard coding it)?

推荐答案

您可以使用

You can use the callBy, which respects the default values:

::function.callBy(emptyMap()) // is just function()

如果您有许多没有默认值的参数,事情将会变得混乱:

Things will be messy if you have many parameters without default values:

fun foo(a: Int, b: String = "") {}
val ref = ::foo
val params = ref.parameters
ref.callBy(mapOf(params[0] to 1))  // is just foo(1)

如果您的函数是非对象类型的成员函数,或者是扩展函数,或者是作为(其他)非对象类型的成员函数的类型的扩展函数,那将更加无聊.

It will be even more boring if your function is a member function of a non-object type, or it's extension function, or it's an extension function to a type as a member function of a (other) non-object type.

我写了一种减少样板的便捷方法:

I wrote a convenient method to reduce boilerplate:

fun <R> KFunction<R>.callNamed(params: Map<String, Any?>, self: Any? = null, extSelf: Any? = null): R {
    val map = params.entries.mapTo(ArrayList()) { entry ->
        parameters.find { name == entry.key }!! to entry.value
    }
    if (self != null) map += instanceParameter!! to self
    if (extSelf != null) map += extensionReceiverParameter!! to extSelf
    return callBy(map.toMap())
}

用法:

fun String.foo(a: Int, b: String = "") {}
fun foo(a: Int, b: String = "") {}
class Foo {
    fun bar(a: Int, b: String = "") {}
    fun String.baz(a: Int, b: String = "") {}
}

::foo.callNamed(mapOf("a" to 0))
String::foo.callNamed(mapOf("a" to 0), extSelf = "")
Foo::bar.callNamed(mapOf("a" to 0), Foo())
// function reference don't work on member extension functions
Foo::class.declaredFunctions.find { it.name == "baz" }!!.callNamed(mapOf("a" to 0), Foo(), "") 

这篇关于反射调用函数并使用默认参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆