Kotlin 通用接口解析器

Kotlin generic interface resolver

我正在尝试构建一个解析器,给定一些域上下文 return 支持通用接口的实现。代码如下(域抽象):

interface Interface<T>

class StringImplementation: Interface<String>

class BooleanImplementation: Interface<Boolean>

class Resolver {

    fun <T : Any> resolve(implementation: String): Interface<T> {
        return when (implementation) {
            "string" -> StringImplementation()
            "boolean" -> BooleanImplementation()
            else -> throw IllegalArgumentException()
        }
    }

}

这段代码看起来不错,但编译器在抱怨,因为第 11 行 Type missmatch: Required: Interface<T> Found: StringImplementation 和第 12 行 Type missmatch: Required: Interface<T> Found: BooleanImplementation

为什么这是个问题?我虽然在方法合同中设置 <T : Any> 将允许 return 任何类型的实现。这里的约束是方法resolve的return类型必须是Interface<T>,换成Interface<*>会让编译器闭嘴,但这不是我们需要的。

TL;DR

一个函数只能有 1 种 return 类型,但是你的函数有 2 种不同的 return 类型。

只有这个行得通:

interface Interface<T>

class StringImplementation: Interface<String>

class BooleanImplementation: Interface<Boolean>

class Resolver {

    fun resolve(implementation: String): Interface<*> { // <-- star
        return when (implementation) {
            "string" -> StringImplementation()
            "boolean" -> BooleanImplementation()
            else -> throw IllegalArgumentException()
        }
    }

}

说明

从函数定义的角度来看,它必须有明确的、明确的return类型。 Interface<T> 说应该是扩展 Interfaceexplicit 类型 T 具体实现可以在开头知道函数的执行
当您调用 resolve 时,您的代码无法知道 T 会是什么。您还能如何想象该函数会 return 返回什么?!

缩短:一个函数可以恰好有 1 种 return 类型,但是你的函数有 2 种不同的 return 类型(Interface<String> / Interface<Boolean>)。

Continue to read here 如果您想深入研究泛型并获得更技术性的描述。

编译器不知道 T 是否匹配 implementation 变量。即使 implementationstringT 也可能是 String 的另一种类型。因此,您可以像@Neo 提到的那样擦除通用类型,或者您需要转换 return 类型。

interface Interface<T>

class StringImplementation: Interface<String>

class BooleanImplementation: Interface<Boolean>

class Resolver {

    inline fun <reified T : Any> resolve(): Interface<T> {
        return when (T::class) {
            String::class -> StringImplementation() as Interface<T>
            Boolean::class -> BooleanImplementation() as Interface<T>
            else -> throw IllegalArgumentException()
        }
    }
}

要获得更高的类型安全性,您可以使用具体化参数并使用它来解析类型。 (注意演员表还是有必要的)

I though setting <T : Any> in the method contract would allow to return an implementation of any type.

不,这意味着它具有到return任何类型的实现调用者要求。例如,在 Animesh Sahu 的示例中,resolve<Boolean>("string") 必须 return 和 Interface<Boolean>,但是您对 resolve 的实现将 return 和 StringImplementation。当然也可以是resolve<File>("string")

allow to return an implementation of any type

被调用的方法选择的恰好是Interface<*>