我正在将一台非常旧的大型Java服务器翻译成Kotlin,并试图在转换过程中尽可能少地更改逻辑。我正在寻找一种方法来翻译这段Java代码,而不从根本上改变它
考虑以下玩具代码:
interface Pet
class Dog : Pet
class Cat : Pet
class PetSitter<T : Pet> {
fun walk(pet: T) {}
}
fun main() {
val sitters: Array<PetSitter<*>> =
arrayOf(PetSitter<Cat>(), PetSitter<Dog>())
sitters[0].walk(Cat()) // Type mismatch.
// Required: Nothing
// Found: Cat
}
这无法通过消息Type mismatch: inferred type is Cat but Nothing was expected
进行编译。
在Java中,以下操作很好:
PetSitter[] sitters = ... // Note: PetSitter's generic is omitted
sitters[0].walk(new Cat());
有可能在Kotlin中类似地定义Array<PetSitter>
(没有宠物通用(吗?或者以其他方式使PetSitter<*>.walk
的参数类型为Pet
而不是Nothing
?
在Java中,这被称为原始类型。只有向后兼容性的必要性才支持它,并且不鼓励使用它,因为它违背了使用泛型的目的。出于同样的原因,Kotlin完全禁止它,因为它没有它必须支持的语言的预泛型版本。
使用原始类型的等效方法是将类型强制转换为允许类型。这个要求是为了迫使你考虑演员阵容是否合适。
(sitters[0] as PetSitter<Cat>).walk(Cat())
更新:请参阅https://stackoverflow.com/a/70114733/2875073这更简单。
Kotlin似乎不允许原始类型,但似乎有一个解决方案是将我的Pet实例强制转换为Pet
,然后生成一个when
事例,枚举每个子类型,并为每个事例强制转换sitters[0]
:
val myPet: Pet = Cat()
when (myPet) {
is Dog -> (sitters[0] as PetSitter<Dog>).walk(myPet)
is Cat -> (sitters[0] as PetSitter<Cat>).walk(myPet)
}