如何使用callBy()调用Kotlin伴侣工厂方法?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何使用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
除了我的short answer,还有一个更技术性的解释:
是的,实际上有一个隐藏的参数,你可以看到它(例如),如果你看看反编译的(到Java)字节码:
public final class StudentWithFactory {
// ...
public static final class Companion {
// ...
@NotNull
public static StudentWithFactory fromJson$default(StudentWithFactory.Companion var0, String var1, int var2, int var3, Object var4) {
// ...
return var0.fromJson(var1, var2);
}
// ...
}
}
第一个参数(var0
)实际上是伴随对象的一个实例。 var1
(名称)和var2
(年龄)是您声明的参数。 var3
是一个位掩码,用于确定是否已传递显式值或是否应使用默认值*。老实说,我不知道var4
是为了什么。它在Java代码中未使用。但是导入的部分是你只需要担心var0
,var1
和var2
,如果你想调用这个函数。
因此,最终实际上在伴随对象的实例上调用了fromJson *的非静态版本:
var0.fromJson(var1, var2)
*为简单起见留下代码
您可以使用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
))
以上是关于如何使用callBy()调用Kotlin伴侣工厂方法?的主要内容,如果未能解决你的问题,请参考以下文章