我想創建一個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一些用戶名!關於順序,我看到的問題是首先收集所有原因,然後返回匹配的原因(如果有的話)。但是如果我們找到一個匹配,則不需要重複;你聲稱序列比遞歸更快似乎理論上並不成立。 –