zju*_*asz 5 reflection type-safety kotlin
我试图检查一个类型是否符合if表达式的另一个类型,如下所示:
if (String::class is Any::class)
Run Code Online (Sandbox Code Playgroud)
这给了我不支持空左侧的错误类文字.任何人都可以详细说明这个错误和/或告诉我应该怎么做这个检查?
编辑(澄清):我不能进行相等检查,因为我需要知道左边的类是与右边的类匹配还是它的子类.因此,如果左侧类的实例可以安全地转换为右侧的类.
基本上我需要相当于:
if ("A string" is Any)
Run Code Online (Sandbox Code Playgroud)
但是没有String实例,String只是在这里使用了一个例子.
我想不清楚 Kotlin 是否is在 aKClass和 another之间以不同的方式使用运算符,KClass就像在实例和类型之间那样,这就是为什么我试图做的事情不起作用。无论如何,我制作了这个小中缀函数来模仿功能。然而,它当然只适用于 JVM 目标,因为它使用的是 Java 反射。这与此 SO post 中给出的答案不符。
infix fun <T : Any, C : Any> KClass<T>.can(comparate: KClass<C>) =
comparate.java.isAssignableFrom(this.java)
Run Code Online (Sandbox Code Playgroud)
这将允许您完全按照我正在尝试执行的操作,但使用can函数而不是 is 运算符,如下所示:
if(String::class can Any::class)
Run Code Online (Sandbox Code Playgroud)
您的错误消息是is检查需要类名,而不是对右侧 KClass 的引用。消息本身可能有点不清楚。但这同样适用于 Java,您不会使用instanceOf运算符,而是调用isAssignableFrom.
如需解决问题的帮助,您可以在 Github 中找到示例...
Klutter 库中提供了Class、KClass、Type和KType以及原语之间的许多 instanceOf 样式检查组合的示例。您可以从那里复制想法。从长远来看,您可能希望涵盖多种组合。
以下是大量扩展组合的示例,用于检查一种类型是否可从另一种类型分配。一些例子是:
fun <T : Any, O : Any> KClass<T>.isAssignableFrom(other: KClass<O>): Boolean {
if (this.java == other.java) return true
return this.java.isAssignableFrom(other.java)
}
fun <T : Any> KClass<T>.isAssignableFrom(other: Class<*>): Boolean {
if (this.java == other) return true
return this.java.isAssignableFrom(other)
}
fun KClass<*>.isAssignableFromOrSamePrimitive(other: KType): Boolean {
return (this.java as Type).isAssignableFromOrSamePrimitive(other.javaType)
}
fun KClass<*>.isAssignableFromOrSamePrimitive(other: Type): Boolean {
return (this.java as Type).isAssignableFromOrSamePrimitive(other)
}
fun Type.isAssignableFromOrSamePrimitive(other: Type): Boolean {
if (this == other) return true
if (this is Class<*>) {
if (other is Class<*>) {
return this == other.kotlin.javaObjectType || this == other.kotlin.javaPrimitiveType ||
this.isAssignableFrom(other)
}
return this.isAssignableFrom(other.erasedType())
}
return this.erasedType().isAssignableFrom(other.erasedType())
}
// ... and so on for every permutation of types
Run Code Online (Sandbox Code Playgroud)
请参阅所有排列的链接源。
您将需要上述示例使用的erasedType()扩展- 从Typeback 到 a Class(类型擦除后):
@Suppress("UNCHECKED_CAST") fun Type.erasedType(): Class<Any> {
return when (this) {
is Class<*> -> this as Class<Any>
is ParameterizedType -> this.getRawType().erasedType()
is GenericArrayType -> {
// getting the array type is a bit trickier
val elementType = this.getGenericComponentType().erasedType()
val testArray = java.lang.reflect.Array.newInstance(elementType, 0)
testArray.javaClass
}
is TypeVariable<*> -> {
// not sure yet
throw IllegalStateException("Not sure what to do here yet")
}
is WildcardType -> {
this.getUpperBounds()[0].erasedType()
}
else -> throw IllegalStateException("Should not get here.")
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
445 次 |
| 最近记录: |