簡體   English   中英

Kotlin:密封類中的泛型

[英]Kotlin: Generics in sealed classes

我正在嘗試使用 Kotlin 實現某種規范模式,並且我有以下代碼:

// T is the returning type for each query
sealed class Query<T> { 

  class ByName(val name: String): Query<List<User>>()

  class ById(val name: String): Query<User>()

}

class Repository {
 
  fun <T> find(query: Query<T>): T {
    return when(query) {
        is ByName -> getUsersByName(query.name) 
        // other query types
    }
  }

  private fun getUsersByName(name: String): List<User> { /*...*/ }

}

但我收到一個錯誤:

Type mismatch
Expected: T 
Found: List<User>

如果我將結果轉換為T (通過添加as T ),它會編譯但我收到Unchecked cast警告。 安全嗎?

有沒有辦法在沒有警告的情況下做到這一點?

考慮密封類型時不會考慮泛型。 例如,當編譯器分析is ByName分支時,它不會“啊,我看到T == List<User>在這里!”。

當您強制轉換為T ,編譯器無法生成任何代碼來檢查該強制轉換在那時是否有效,因為在運行時類型參數都被刪除,因此是“未經檢查的強制轉換”。

據我所知,演員表總是安全的,因為你事先檢查了類型。

消除警告的一種方法是內聯函數並具體化類型參數:

inline fun <reified T> find(query: Query<T>) =
    when(query) {
        is Query.ByName -> getUsersByName(query.name) as T
        is Query.ById -> getUsersById(query.name) as T
    }

這意味着getUsersByNamegetUsersById不能再是私有的,但它們可以調用其他私有方法。

這是有效的,因為您現在正在用when表達式替換find每個調用(這就是“內聯”的意思),並且調用者總是知道T是什么(因此具體化了T )。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM