我有这样的东西
fun validate(obj1: Any) {
// Here I am getting the KClass of the object
val objKClass = obj1::class
// Here I am casting the object using KClass
val obj1Cast = objKClass.safeCast(obj1)
// Then I want to iterate over its properties
for (prop in objKClass.memberProperties) {
//And get one BigDecimal? value
val bigDecimal: BigDecimal? = prop.get(obj1Cast) as BigDecimal?
}
}
这不起作用,我和prop.get(obj1Cast)
有关
Type mismatch.
Required:
Nothing
Found:
Any?
是否有另一种方法来访问memberProperties的值并将其转换为BigDecimal?(例如)给定一个类型为Any的对象作为我函数的输入?
发布于 2022-10-07 12:56:34
使用泛型类型捕获来解决此问题。
在当前代码中,prop
是KProperty1<out Any, *>
类型。这是因为obj1
的类型是Any
,所以objKClass
的类型是KClass<out Any>
。当将out Any
类型用作输入参数时,没有满足该类型的值,因此您将得到一个编译错误。
第一步是捕获obj1
的类型。我们可以为它添加一个泛型类型参数,而不是使用Any
。让我们调用捕获的类型T
。
fun <T: Any> validate(obj1: T) {
val objKClass: KClass<out T> = obj1::class
val obj1Cast = objKClass.safeCast(obj1) ?: return
for (prop in objKClass.memberProperties) {
val bigDecimal: BigDecimal? = prop.get(obj1Cast) as BigDecimal?
}
}
现在,prop
的类型是KProperty1<out T, *>
。这使我们走近了一步,但我们仍然有一个编译错误。这是因为out T
只能用于输出值,但我们希望将T
传递给方法参数。
幸运的是,safeCast
可以帮助我们,因为它将缩小值的类型,从而与类的类型完全匹配。我们只需要通过使用第二种方法来捕获类的确切类型来提供一些帮助。让我们把更窄的精确类型称为T2
。
// Here we capture the type of the object as T,
// and get its class as KClass<out T>
fun <T: Any> validate(obj1: T) {
validate(obj1, obj1::class)
}
// Here we narrow the type of the object from T to T2
fun <T: Any, T2: T> validate(obj1: T, type: KClass<T2>) {
val obj1Cast = type.safeCast(obj1) ?: return
for (prop in type.memberProperties) {
val bigDecimal: BigDecimal? = prop.get(obj1Cast) as BigDecimal?
}
}
现在,它不存在编译错误。有关如何工作的更多信息,您可以阅读有关“泛型类型捕获”。
https://stackoverflow.com/questions/73987235
复制相似问题