我想创建一个Throwable
扩展函数,给定一个KClass
,递归搜索与参数匹配的根本原因。下面是一个尝试的作品:Kotlin:泛型和变异
fun <T : Throwable> Throwable.getCauseIfAssignableFrom(e: KClass<T>): Throwable? = when {
this::class.java.isAssignableFrom(e.java) -> this
nonNull(this.cause) -> this.cause?.getCauseIfAssignableFrom(e)
else -> null
}
这工作太:
fun Throwable.getCauseIfAssignableFrom(e: KClass<out Throwable>): Throwable? = when {
this::class.java.isAssignableFrom(e.java) -> this
nonNull(this.cause) -> this.cause?.getCauseIfAssignableFrom(e)
else -> null
}
我调用该函数像这样:e.getCauseIfAssignableFrom(NoRemoteRepositoryException::class)
。
然而,Kotlin docs约泛型说:
这就是所谓的声明站点变化:我们可以标注来源的 类型参数T,以确保(生产)它只返回 从成员来源,并从未消费。要做到这一点,我们提供 out修饰符
abstract class Source<out T> {
abstract fun nextT(): T
}
fun demo(strs: Source<String>) {
val objects: Source<Any> = strs // This is OK, since T is an out-parameter
// ...
}
在我的情况下,参数e
不返回,而是消耗。在我看来,它应该被宣布为e: KClass<in Throwable>
,但不能编译。但是,如果我认为out
为“只能读取或返回”,而in
则为“只能写入或为其分配值”,那么这是有道理的。有人可以解释吗?
嘿,只注意到你的递归函数为总理候选人一个序列:'generateSequence(this){it.cause} .first {it :: class.java.isAssignableFrom(e.java)}'应该是行为兼容的,IMO会更快地消耗精神上的力量,并且也会摆脱递归。不要编辑问题,因为它可能会使当前答案无效。 –
你用你的方法调用Throwable的派生类,所以当你将参数定义为KClass <在Throwable>中时,你应该期望编译错误,对吗? – Les
@ mEQ5aNLrK3lqs3kfSa5HbvsTWe0nIu一些用户名!关于顺序,我看到的问题是首先收集所有原因,然后返回匹配的原因(如果有的话)。但是如果我们找到一个匹配,则不需要重复;你声称序列比递归更快似乎理论上并不成立。 –