reflection - 如何使用 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
解决方案
您可以使用该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
))
推荐阅读
- node.js - 文件数超过限制时如何捕获 MulterError: Unexpected field?
- python - 是否可以使用 pymsteams 将 markdown 设置为 False?
- php - 从 URL 中删除文件名并在 URL 中保留 2 个 GET 变量?
- python - 在 python 中,如果 v 是 (1,3) numpy 数组,为什么 v[0,:] (3,) 而 v[:,:] 是 (1,3)?
- docker - 在 docker 容器上运行 Jenkins。无法连接到 unix:///var/run/docker.sock 上的 Docker 守护程序。docker 守护进程是否正在运行?
- openmdao - 计数功能评估
- javascript - Onmousedown 事件函数处理无法获取外部变量的值
- sql - 如何有效地从 INNER JOINed 表中选择聚合 SUM 值?
- c++ - std::map 异常 [ 读取访问冲突 _Wherenode 为 nullptr。]
- python - 为共享共同值的每一行合并数据框中列的内容