Kotlin:返回一个通用的接口
在Kotlin,我试图编译以下内容:
- 给定一个与泛型类型的接口(Printer)
- 和该接口的两个实现(DogPrinter和CatPrinter)
- 根据外部变量(AnimalType)返回其中一台打印机
下面的代码不能编译,因为需要一个类型: fun getMapper(animalType: AnimalType): Printer
我试图使用<Any>
或<*>
但没有成功。 有人可以帮忙吗?
(通过将以下代码复制到https://try.kotlinlang.org,很容易看出错误)
enum class AnimalType { CAT, DOG } class Dog class Cat interface Printer<in T> { fun mapToString(input: T): String } class DogPrinter : Printer<Dog> { override fun mapToString(input: Dog): String { return "dog" } } class CatPrinter : Printer<Cat> { override fun mapToString(input: Cat): String { return "cat" } } private fun getMapper(animalType: AnimalType): Printer { return when(animalType) { AnimalType.CAT -> CatPrinter() AnimalType.DOG -> DogPrinter() } } fun usage_does_not_compile() { getMapper(AnimalType.DOG) .mapToString(5) }
我修改了一下你的代码。 getMapper
函数现在与reified
泛化类型inline
,这使getMapper<Dog>()
的调用非常可读。
阅读关于这里的具体 reified
: Kotlin中的关键字关键字是什么?
private inline fun <reified T> getMapper(): Printer<T> { when (T::class) { Cat::class -> return CatPrinter() as Printer<T> Dog::class -> return DogPrinter() as Printer<T> } throw IllegalArgumentException() } fun main(args: Array<String>) { println(getMapper<Dog>().mapToString(Dog())) println(getMapper<Cat>().mapToString(Cat())) }
事实上甚至没有必要,但是使得客户端更具可读性。 或者,您也可以将该类作为参数传递给getMapper
函数。 真正重要的是使这个通用 。 不加限制的演员阵容不是很酷,但在这里似乎很安全。
Kotlin没有原始类型,所以你不能从getMapper
返回Printer
。 您可以返回Printer<*>
,使getMapper
通用,或者将您的继承结构更改为具有公共超类型。
返回Printer<*>
正常工作。 但它不是实际有用的,因为你不能调用mapToString(Dog())
(我认为mapToString(5)
是一个错字),这是一件好事:如果它编译
getMapper(AnimalType.CAT).mapToString(Dog())
也将不得不编译,因为返回类型只能取决于参数类型 ,而不是值 ,而AnimalType.CAT
和AnimalType.DOG
具有相同的类型。 有一些语言允许它,但Kotlin不是其中之一。