在Kotlin中,我尝试编译以下内容:

  • 提供了具有通用类型的接口(interface)(打印机)
  • 和该接口(interface)的两个实现(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函数是inline,现在具有reified泛型类型,这使得该调用在getMapper<Dog>()上可读性强。

    在此处阅读有关reified的信息:What does the reified keyword in Kotlin really do?

    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函数。真正重要的部分是使这一个通用
    未经检查的 Actor 阵容不是很酷,但在这里似乎很安全。

    08-05 19:19