我有一个抽象类ConfigGroup,它有一个超类ConfigElement。在ConfigElement中,定义了toJson()方法。ConfigGroup将覆盖此方法。
目前ConfigGroup中的toJson()看起来像这样:
override fun toJson(): JsonObject {
val map: HashMap<String, JsonObject> = HashMap()
for (child in this::class.declaredMemberProperties) {
map[child.name] = (child.get(this) as ConfigElement).toJson()
}
return JsonObject(map)
}
但是当我试图编译它时,我得到Type mismatch: inferred type is ConfigGroup but Nothing was expected
我有点困惑,因为它几乎与Kotlin: Iterate over components of object中的示例相同。唯一的区别是,我试图从同一个类中获取属性,因此必须使用this
关键字。
1条答案
按热度按时间ttp71kqs1#
这里的问题是,Kotlin编译器不够聪明,无法理解您对
::class
和get()
使用的是完全相同的对象。在这种特定情况下,这是类型安全的,可以被允许。然而,在更一般的情况下,从对象获取KProperty
并使用它来获取值不是类型安全的,Kotlin故意不允许它。我们可以用与其他情况相同的方式来解决这个问题,即编译器不理解代码是类型安全的-通过进行未检查的强制转换:
但是等等,为什么获取类型为
Animal
的变量的成员,然后对animal
示例使用它不是类型安全的呢?难道不能保证animal
拥有动物所需的所有成员吗?不完全是我们可以从狗身上获得一些成员,然后用它们来对付猫,因为它们都是动物。在
printProperties
内部,animal1
和animal2
都是Animal
类型,但它们的运行时类型不同,因此从animal1
获取属性并将其用于animal2
不是类型安全的。Kotlin通过使用方差来防止这种类型的问题。如果我们执行
Animal::class
,我们得到一个KClass<Animal>
,所以我们可以使用这个类来消费动物对象。但是如果我们做animal::class
,我们得到KClass<out Animal>
,因为我们不能确定animal
的确切类型。KClass<out Animal>
基本上说我们有一个KClass
的动物或其亚型之一,我们不知道是哪一个。默认情况下,我们不能使用这个KClass
来消费动物对象。在您的特定情况下,可以保证我们从完全相同的运行时类型获取
KClass
,然后尝试使用,因此这是类型安全的,我们可以安全地使用未经检查的强制转换。