尚不支持左侧为空的 Kotlin class 文字?
Kotlin class literals with empty left hand side are not yet supported?
我正在尝试使用如下 if 表达式检查一种类型是否符合另一种类型:
if (String::class is Any::class)
这给我错误 class 尚不支持左侧为空的文字。任何人都可以详细说明该错误 and/or 告诉我应该如何进行此检查?
编辑(澄清):我无法进行相等性检查,因为我需要知道左侧的 class 是否与右侧的 class 匹配或者是子 class 的。因此,如果左侧 class 的实例可以安全地转换为右侧 class 的实例。
基本上我需要相当于:
if ("A string" is Any)
但是没有 String 实例,String 只是在这里用作示例。
我想不清楚 Kotlin 在 KClass
和另一个 KClass
之间使用 is
运算符的方式是否与在实例和类型之间的方式不同,这就是为什么我试图做的是行不通的。无论如何,我做了这个小中缀函数来模仿功能。然而,它当然只适用于 JVM 目标,因为它使用 Java 反射。这是从 .
开始的
infix fun <T : Any, C : Any> KClass<T>.can(comparate: KClass<C>) =
comparate.java.isAssignableFrom(this.java)
这将允许你做我想做的事情,但使用 can
函数而不是像这样的 is 运算符:
if(String::class can Any::class)
您的错误消息是 is
检查需要一个 class 名称,而不是对右侧 KClass 的引用。消息本身可能有点不清楚。但同样适用于 Java,您不会使用 instanceOf
运算符,而是调用 isAssignableFrom
.
有关解决问题的帮助,您可以在 Github...
中找到示例
在Klutter library中有很多instanceOf样式检查组合的例子,在Class
、KClass
、Type
和KType
之间以及原语。你可以从那里复制想法。您可能希望在长 运行.
中涵盖许多组合
这里是 a big mix of extensions 的示例,用于检查一种类型是否可以从另一种类型分配。一些例子是:
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
见linked source for all permutations。
并且您将需要上述示例使用的 erasedType()
extension——它从 Type
返回到 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.")
}
}
我正在尝试使用如下 if 表达式检查一种类型是否符合另一种类型:
if (String::class is Any::class)
这给我错误 class 尚不支持左侧为空的文字。任何人都可以详细说明该错误 and/or 告诉我应该如何进行此检查?
编辑(澄清):我无法进行相等性检查,因为我需要知道左侧的 class 是否与右侧的 class 匹配或者是子 class 的。因此,如果左侧 class 的实例可以安全地转换为右侧 class 的实例。
基本上我需要相当于:
if ("A string" is Any)
但是没有 String 实例,String 只是在这里用作示例。
我想不清楚 Kotlin 在 KClass
和另一个 KClass
之间使用 is
运算符的方式是否与在实例和类型之间的方式不同,这就是为什么我试图做的是行不通的。无论如何,我做了这个小中缀函数来模仿功能。然而,它当然只适用于 JVM 目标,因为它使用 Java 反射。这是从
infix fun <T : Any, C : Any> KClass<T>.can(comparate: KClass<C>) =
comparate.java.isAssignableFrom(this.java)
这将允许你做我想做的事情,但使用 can
函数而不是像这样的 is 运算符:
if(String::class can Any::class)
您的错误消息是 is
检查需要一个 class 名称,而不是对右侧 KClass 的引用。消息本身可能有点不清楚。但同样适用于 Java,您不会使用 instanceOf
运算符,而是调用 isAssignableFrom
.
有关解决问题的帮助,您可以在 Github...
中找到示例在Klutter library中有很多instanceOf样式检查组合的例子,在Class
、KClass
、Type
和KType
之间以及原语。你可以从那里复制想法。您可能希望在长 运行.
这里是 a big mix of extensions 的示例,用于检查一种类型是否可以从另一种类型分配。一些例子是:
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
见linked source for all permutations。
并且您将需要上述示例使用的 erasedType()
extension——它从 Type
返回到 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.")
}
}