首页 > 解决方案 > 如何使用 callBy() 调用 Kotlin 配套工厂方法?

问题描述

我有代码接受一个类作为参数,并准备数据以调用该类的构造函数,如果存在工厂方法,则为伴随对象工厂方法。

调用构造函数时一切正常,但出现错误

java.lang.IllegalArgumentException: No argument provided for a required parameter: instance of fun nz.salect.objjson.JVMTest.StudentWithFactory.Companion.fromJson(kotlin.String, kotlin.Int): nz.salect.objjson.JVMTest.StudentWithFactory

调用工厂方法时。有问题的工厂方法:

data class StudentWithFactory(val name: String, val years: Int=0) {

    companion object {

        fun fromJson(name: String="", age: Int = 0):StudentWithFactory {
            return StudentWithFactory(name, age)
        }
    }
}

没有必需的参数,除非有一些隐藏参数。有任何想法吗?

事实上,我恢复了完全删除参数fromJson并使用::fromJson.callby(emptyMap()). 同样的错误。

很明显,伴随方法至少需要一个附加参数。也许是班级?还是伴生对象?如何指定所需的参数?

构建 callBy() 的函数提供了一个类(或从提供的类中查找类)以及 json 名称和值。

var funk:KFunction<*>?=null
val companionFuncs=cls.companionObject?.declaredMemberFunctions
if(companionFuncs?.size ?:0 >0){
    companionFuncs?.forEach {
        if(it.name == "fromJson") funk=it
    }

}
val cons:KFunction<T> = if(funk != null)
       funk as KFunction<T>
    else
       cls.primaryConstructor ?: throw IllegalArgumentException("no primary constructor ${cls.simpleName}")
val valuesMap = cons.parameters.filter{it.name in vals}
    .associateBy(
    {it},
    {generateValue(it)}
)
val data = cons.callBy(valuesMap) //as T
return data

标签: reflectionkotlinkotlin-companion

解决方案


您可以使用该parameters属性来确定必须将多少参数传递给函数/构造函数。

如果你打电话

val paramsConstr = StudentWithFactory::class.primaryConstructor?.parameters

paramsConstr如预期的那样大小为 2,但如果你打电话

val paramsFunc = ::fromJson.parameters

paramsFunc将是三号。第一个元素对应于伴随对象的实例。所以,这就是您需要提供的参数列表。

您可以这样调用fromJson

// not using any default parameters
::fromJson.callBy(mapOf(
        paramsFunc[0] to StudentWithFactory::class.companionObjectInstance,
        paramsFunc[1] to "Hello",
        paramsFunc[2] to 30
))

// using only the default parameter for "name"
::fromJson.callBy(mapOf(
        paramsFunc[0] to StudentWithFactory::class.companionObjectInstance,
        paramsFunc[2] to 30
))

推荐阅读