我想建立一个解析器,给定一些域上下文,返回一个通用接口的实现。代码如下(域抽象化)。
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<*>
会让编译器闭嘴,但这不是我们需要的。
一个函数可以只有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>
).
继续阅读 如果你想深入了解通用性,并获得更多的技术描述。
编译器无法知道 T
匹配 implementation
变量。即使 implementation
是 string
, 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()
}
}
}
为了有更多的类型安全,你可以使用一个重构参数,然后用它来解析类型。(请注意,仍然需要进行转码)
我虽然设置
<T : Any>
方法契约中允许返回任何类型的实现。
不,这意味着它 有 返回任何类型的实现 来电者要求. 例如,在Animesh Sahu的例子中。resolve<Boolean>("string")
必须返回一个 Interface<Boolean>
但你的实施 resolve
将返回一个 StringImplementation
. 当然,它也可能是 resolve<File>("string")
等。
允许返回任何类型的实现
其中 被叫方法 选择的正是 Interface<*>
.