作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
KClass
定义为 public interface KClass<T : Any> : KDeclarationContainer, KAnnotatedElement, KClassifier
这很棘手,因为类 String?
应该是 KClass<String>
,但无法获得。
鉴于以下 3 个示例(它们都应该做本质上相同的工作),其中 1 个无法编译,而其他示例返回相同的运行时类型。
inline fun <reified T> test1(): Any = T::class
inline fun <reified T: Any> test2(): KClass<T> = T::class
inline fun <reified T> test3(): KClass<T> = T::class // does not compile
test1<String?>() // class kotlin.String
test1<String>() // class kotlin.String
test2<String?>() // does not compile
test2<String>() // class kotlin.String
test1
的运行时行为?具有
test2
的编译时行为(和安全性) ?
inline fun <reified T> test4() {
val x = T::class // compiles, implied type of x is KClass<T>
val y: KClass<T> = T::class // does not compile with explicit type of KClass<T>
}
class OutputContract<T>(
private val output: () -> T,
val outputType: KClass<T> // ERROR!
) {
fun invoke(): T {
return output()
}
}
inline fun <reified T> output(noinline output: () -> T): OutputContract<T> {
return OutputContract(output, T::class)
}
KClass<T>
,不与
T::class
,嗡嗡作响就好了。我希望允许消费者将可空性指定为契约(Contract)的一部分,因此添加了
Any
约束将不起作用。如果我只是转
KClass<T>
进入
KClass<Any>
,这一切都有效(这证明没有运行时问题,只有编译时间)。这最终是我选择的解决方法,但如果我能真正保持正确的类型,那就太好了。
最佳答案
您的问题缺少最重要的信息。您展示了将您的函数调用为 myFun<String?>()
的人为案例,但如果是这种情况,您显然可以将其更改为不使用可空类型。所以这可能不是真正的用例。您过于简化了您的解释并删除了我们需要回答您的问题的最相关信息:“完整的方法签名是什么,调用站点是什么样的?”
缺少的是你如何推断你的类型 T
?您可以从返回值、方法参数或通过在每个调用站点中显式声明它来获取它。因此,您可以选择在您的函数中使用 T: Any
,并根据您未在问题中显示的信息来决定哪个最好。
所以这里有你的选择:
// call site, any return type nullable or not
val something: String? = doSomething()
// function
inline fun <reified T: Any> doSomething(): T? {
val x: KClass<T> = T::class
// ...
}
// call site, any parameter type nullable or not
val param: String? = "howdy"
doSomethingElse(param)
// function
inline fun <reified T: Any> doSomethingElse(parm: T?) {
val x: KClass<T> = T::class
// ...
}
// call site, any non-nullable generic parameter
doSomething<String>()
// function
inline fun <reified T: Any> doSomethingElse() {
val x: KClass<T> = T::class
// ...
}
// call site: whatever you want it to be
// function:
inline fun <reified T> test4() {
val x = T::class // compiles, implied type of x is KClass<T>
val y: KClass<*> = T::class KClass<T>
}
x
和 y
的作用相同,并且 KClass
引用中将缺少某些方法/属性。 T
类型?什么是与上述不兼容的模式?
<T: Any>
和
T?
组合的技巧。
output
函数引用的预期保持可空性,但允许它适用于 KClass
:
class OutputContract<T: Any>(private val output: () -> T?, val outputType: KClass<T>) {
fun invoke(): T? {
return output()
}
}
inline fun <reified T: Any> output(noinline output: () -> T?): OutputContract<T> {
return OutputContract(output, T::class)
}
T
进行可空性控制,但在内部将其用作类型化
KClass
,但您可以将其用作
KClass<*>
,具体取决于您从
KClass
使用的功能。你可能不会遗漏任何重要的东西。你没有展示你打算用
KClass
做什么,所以很难说更多关于这个话题的内容。
KClass
通常不是一个好用的类型,如果您认为它们可能会传递给您一个泛型类,您应该使用
KType
代替。
关于kotlin - 以允许可为空类型和使用该类型参数声明 `KClass<T>` 的方式声明函数泛型类型参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49620173/
我是一名优秀的程序员,十分优秀!