Kotlin通用接口解析器

问题描述 投票:0回答:1

我想建立一个解析器,给定一些域上下文,返回一个通用接口的实现。代码如下(域抽象化)。

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()
        }
    }

}

这段代码在我看来很好 但编译器却在抱怨因为 Type missmatch: Required: Interface<T> Found: StringImplementation 在第11行和 Type missmatch: Required: Interface<T> Found: BooleanImplementation 在第12行。

为什么会有这个问题?我以为设置 <T : Any> 的方法合同中允许返回任何类型的实现。这里的限制条件是方法的返回类型必须是 resolve 必须 Interface<T>,取而代之的是 Interface<*> 会让编译器闭嘴,但这不是我们需要的。

kotlin generics interface compilation implementation
1个回答
1
投票

TL;DR

一个函数可以只有1个返回类型,但你的函数有2个不同的返回类型。

只有这样才行得通。

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()
        }
    }

}

解释

从函数定义的角度看,它必须有一个明确的、清晰的返回类型。Interface<T> 说它应该是一些扩展的 Interface明确 类型 T 哪些具体的实现可以在执行开始时就能知道。 的函数。在你的代码中,没有办法知道什么是 T 将是当你打电话 resolve. 不然你怎么想象函数知道会返回什么呢!?

缩短了。一个函数可以只有一个返回类型,但你的函数有两个不同的返回类型(Interface<String> Interface<Boolean>).

继续阅读 如果你想深入了解通用性,并获得更多的技术描述。


1
投票

编译器无法知道 T 匹配 implementation 变量。即使 implementationstring, T 庶几 String. 所以,你要么像@Neo提到的那样擦掉通用类型,要么就需要铸造返回类型。

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()
        }
    }
}

为了有更多的类型安全,你可以使用一个重构参数,然后用它来解析类型。(请注意,仍然需要进行转码)


1
投票

我虽然设置 <T : Any> 方法契约中允许返回任何类型的实现。

不,这意味着它 返回任何类型的实现 来电者要求. 例如,在Animesh Sahu的例子中。resolve<Boolean>("string") 必须返回一个 Interface<Boolean>但你的实施 resolve 将返回一个 StringImplementation. 当然,它也可能是 resolve<File>("string") 等。

允许返回任何类型的实现

其中 被叫方法 选择的正是 Interface<*>.

© www.soinside.com 2019 - 2024. All rights reserved.