我的問題是,當一個通用類實作了一個介面時,我無法將其實體化。
實體化代碼如下;
class MainClass {
fun mainMethod(){
val access = EADBAccess<AppUserModel> (AppUserModel::class.java)
}
在這個主類中,我生成了一個錯誤。 這個錯誤是
其他相關的類在下面。
EADBModelI介面
interface EADBModelI{
var id: 繩索
}
AppUserModel類
class AppUserModel : EADBModelI {
override var id: 編碼
get() = id
set(value) { id = value }
var name: String
get() = name
set(value) { name = value}。
}
EADBAccess類
Class EADBAccess<in T : EADBModelI> (private val typeParameterClass: Class<T>) {
fun getSingleDocument( source: Source = Source.DEFAULT, docRef: DocumentReference, handler: ResultHandlerI<T>) {
docRef.get(source).addOnCompleteListener { taskResult ->
if (taskResult.isSuccessful) {
val snapshot = taskResult.result
if (snapshot!!.existence()) {
val model : T = snapshot.toObject(typeParameterClass)
model!!.id = snapshot.reference.id
handler.onSuccess(model)
}
} else {
handler.onFailure(taskResult.exception)
}
}
}
ResultHandlerI介面
interface ResultHandlerI<T> /span>{
fun onSuccess(data: T)
fun onFailure(e: Exception)
uj5u.com熱心網友回復:
我復制了你的代碼并使其可執行(見本答案底部的 "可運行代碼")。當我運行它時,我得到一個錯誤:
型別引數T被宣告為'in',但卻出現在'invariant'
型別ResultHandlerI<T>中的位置。
錯誤的位置
這發生在什么地方?那么首先,型別引數T被定義在EADBAccess類中。T被標記為in.
class EADBAccess<in T : EADBModelI>
當T也被用作fun getSingleDocument的引數handler時,會發生錯誤:
fun getSingleDocument(source: String, docRef: String, handler: ResultHandlerI<T>){
/ .../span>
tl;dr
快速修復是洗掉in。
class EADBAccess<T : EADBModelI>
現在當我運行代碼時,它編譯、運行并列印:
success: AppUserModel(id='docRef', name='source')
解說
Kotlin 檔案Generics: in, out, where詳細說明了。[...] Kotlin提供了一個[...]變數注釋。
in。它使一個型別引數contravariant,意味著它只能被消費而不能被生產。
Array<in String>對應于Java的Array<? super String>。
因此,如果使用<in T : EADBModelI>,那么T將是EADBModelI介面的某個未知實作。但是這還不夠清楚--ResultHandlerI需要知道一個不變數 T,而不是一個變數范圍。
雖然一方面T是一個輸入(所以in T有意義),實際上,T也是一個輸出,因為它被用來定義ResultHandlerI的型別。
定義<T : EADBModelI>使得T不變 - 在運行時它將是EADBModelI的一個單一的、具體的實作(在你的例子中它是AppUserModel)。T的這個實作既可以作為一個輸入,也可以作為一個輸出。
參見這個答案以獲得更多的解釋
。本身允許輸入的函式引數在邏輯上等同于函式的回傳值,而后者顯然處于 "輸出 "位置。
可運行代碼
fun main(){
val access = EADBAccess<AppUserModel> (AppUserModel::class.java)
access.getSingleDocument("source", "docRef", PrintResult()
}
interface EADBModelI{
var id: 繩索
}
class AppUserModel : EADBModelI {
override var id: String = ""/span>
var name: String = ""/span>
override fun toString() = "AppUserModel(id='$id', name='$name')"
}
class EADBAccess<in T : EADBModelI>(private val typeParameterClass: Class<T>) {
fun getSingleDocument( source: String, docRef: String, handler: ResultHandlerI<T>){
//span>簡化的例子
val model = AppUserModel()
model.id = docRef
model.name = source
try {
val result: T = typeParameterClass.cast(model)
handler.onSuccess(result)
} catch (e: Exception) {
handler.onFailure(e)
}
}
}
interface ResultHandlerI<T> {
fun onSuccess(data: T)
fun onFailure(e: Exception)
}
/**假的結果處理程式,將結果列印到控制臺 */
class PrintResult<T> : ResultHandlerI<T> {
override fun onSuccess(data: T) {
println("success: $data")
}
override fun onFailure(e: Exception) {
println("失敗")
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/318595.html
標籤:
下一篇:Java自參考的通用型別

