由于我還不太擅長泛型,所以我想問一下:
問題:為什么我不能通知函式getResult回傳值bundle.getParcelableCompat<T>(BUNDLE_KEY)是型別T(Parcelable 繼承的任何類)?
我得到錯誤:
Cannot use 'T' as reified type parameter. Use a class instead.
我錯過了什么?我雖然傳遞了我想要實作的所有需要??的資訊。
class MyClass<T : Parcelable>(
private val key: String,
private val clazz: Class<T>
) {
private inline fun <reified T : Parcelable> Bundle.getParcelableCompat(name: String): T? =
if (Build.VERSION.SDK_INT >= 33) {
this.getParcelable(name, T::class.java)
} else {
this.getParcelable(name)
}
fun getResult(fragment: Fragment, result: (T) -> Unit) = with(fragment) {
setFragmentResultListener(requestKey) { request, bundle ->
if (request == requestKey) {
val parcelableCompat: T? = bundle.getParcelableCompat<T>(BUNDLE_KEY)
parcelableCompat?.let(result)
}
}
}
}
uj5u.com熱心網友回復:
當您bundle.getParcelableCompat<T>(BUNDLE_KEY)在內部呼叫時getResult T(由 MyClass 洗掉的那個)已經被洗掉,因此 reified 引數對您沒有幫助。考慮一個具體化的引數只是為您節省額外的引數是有幫助的(而且大部分是正確的!)T::class,而不是編譯器為您傳遞它。
但是,您已經保留了一個Class<T>,不需要額外的復雜性。以下應該作業。
class MyClass<T : Parcelable>(
private val key: String,
private val clazz: Class<T>
) {
private inline fun Bundle.getParcelableCompat(name: String): T? =
if (Build.VERSION.SDK_INT >= 33) {
this.getParcelable(name, clazz)
} else {
this.getParcelable(name)
}
fun getResult(fragment: Fragment, result: (T) -> Unit) = with(fragment) {
setFragmentResultListener(requestKey) { request, bundle ->
if (request == requestKey) {
val parcelableCompat: T? = bundle.getParcelableCompat(BUNDLE_KEY)
parcelableCompat?.let(result)
}
}
}
}
uj5u.com熱心網友回復:
正如我在這個答案中所說,Kotlin 中的具體型別引數并不神奇。編譯器在呼叫站點仍然需要一個運行時可用的型別,以便它可以行內您的getParcelableCompat方法。
要查看它是如何不起作用的,只需自己行內它:
fun getResult(fragment: Fragment, result: (T) -> Unit) = with(fragment) {
setFragmentResultListener(requestKey) { request, bundle ->
if (request == requestKey) {
val parcelableCompat: T? = if (Build.VERSION.SDK_INT >= 33) {
this.getParcelable(BUNDLE_KEY, T::class.java)
} else {
this.getParcelable(BUNDLE_KEY)
}
parcelableCompat?.let(result)
}
}
}
看看有沒有T::class.java?您正在嘗試獲取非具體型別引數的類,這是不允許的。
在您getParcelableCompat使用非型別引數類呼叫的情況下,行內會很好。TinT::class.java將替換為您使用的那個類。
由于型別別引數T無法具體化,因此實際上沒有任何意義getParcelableCompat需要具體化型別引數。它可以接受 aClass<T>代替:
class MyClass<T : Parcelable>(
private val key: String,
private val clazz: Class<T>
) {
private fun <T : Parcelable> Bundle.getParcelableCompat(name: String, clazz: Class<T>): T? =
if (Build.VERSION.SDK_INT >= 33) {
this.getParcelable(name, clazz)
} else {
this.getParcelable(name)
}
fun getResult(fragment: Fragment, result: (T) -> Unit) = with(fragment) {
setFragmentResultListener(requestKey) { request, bundle ->
if (request == requestKey) {
val parcelableCompat: T? = bundle.getParcelableCompat(BUNDLE_KEY, clazz)
parcelableCompat?.let(result)
}
}
}
}
或者,根本不要getParcelableCompat通用,因為您可以使用型別T引數MyClass
class MyClass<T : Parcelable>(
private val key: String,
private val clazz: Class<T>
) {
private fun Bundle.getParcelableCompat(name: String): T? =
if (Build.VERSION.SDK_INT >= 33) {
this.getParcelable(name, clazz)
} else {
this.getParcelable(name)
}
fun getResult(fragment: Fragment, result: (T) -> Unit) = with(fragment) {
setFragmentResultListener(requestKey) { request, bundle ->
if (request == requestKey) {
val parcelableCompat: T? = bundle.getParcelableCompat(BUNDLE_KEY)
parcelableCompat?.let(result)
}
}
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/523371.html
標籤:科特林仿制药kotlin-reified-type-parameterskotlin 内联类
上一篇:C#抽象類中的多個泛型型別
