#kotlin #generics
#kotlin #обобщения
Вопрос:
Я хочу создать карту, которая отображает типы классов исключений и связывает функцию для последующего выполнения.
sealed class HttpErrors(open var errorMessage: String = String()) : Throwable()
class UnauthorizedError(override var errorMessage: String) : HttpErrors()
class BadRequestError(override var errorMessage: String) : HttpErrors()
fun handleErrors(actions: HashMap<Class<out Throwable>, () -> Unit>){
...
}
Я вставляю в map и передаю его в функцию:
override fun getItems() {
...
val actions = hashMapOf(BadRequestError::class.java to {presenter.log("Info")})
...
.onDefaultSchedulers(actions)
И мой, который получает карту:
fun <T> Single<T>.onDefaultSchedulers(actions: HashMap<Class<in Throwable>, () -> Unit>): Single<T>
Но редактор жалуется, говоря:
Type mismatch.
Required:
kotlin.collections.HashMap<Class<in Throwable>, () → Unit> /* = java.util.HashMap<Class<in Throwable>, () → Unit> */
Found:
kotlin.collections.HashMap<Class<BadRequestError>, () → Unit> /* = java.util.HashMap<Class<BadRequestError>, () → Unit> */
Я не понял, на что жаловаться, если BadRequestError наследуется от Throwable.
Комментарии:
1.
in
означает контравариантный. Допустимая иерархия типов инвертирована из чего-то, что имеет ковариантныйout
тип (какList
всегда было). Например, функция, которая работает с<in T: Int>
, не может работать с супертипамиInt
, такими какNumber
, потому что она может использовать функцию,Int
которойNumber
нет.2. Исправлено @Tenfour04. Даже без out я получаю ту же ошибку.
Ответ №1:
Это минимальная версия вашего кода, которая воспроизводит ошибку, которую вы наблюдали:
/* does not compile */
sealed class HttpErrors : Throwable()
class BadRequestError : HttpErrors()
fun onDefaultSchedulers(actions: HashMap<Class<out Throwable>, () -> Unit>) {}
fun getItems() {
val actions = hashMapOf(BadRequestError::class.java to {})
onDefaultSchedulers(actions) // <- type mismatch
}
Чтобы заставить его работать, actions
параметру onDefaultSchedulers
требуется двухуровневая ковариация,
- на внешнем
Class<...>
и - на внутреннем
Throwable
.
Итак, если вы объявите это как HashMap<
out
Class<out Throwable>, ...
, код компилируется:
/* compiles */
sealed class HttpErrors : Throwable()
class BadRequestError : HttpErrors()
fun onDefaultSchedulers(actions: HashMap<out Class<out Throwable>, () -> Unit>) {}
fun getItems() {
val actions = hashMapOf(BadRequestError::class.java to {})
onDefaultSchedulers(actions)
}