То, что вы пытаетесь сделать, это преобразование из типа функции (B) -> Int
( источник ) в (A) -> Int
( target ). Это не безопасное преобразование.
Ваша исходная функция (B) -> Int
принимает любой экземпляр, который является B
, , но не обязательно экземпляр типа A
. Более конкретно, он не может обрабатывать все аргументы типа A
, но не типа B
.
Представьте, что ваши занятия выглядят так:
open class A
class B : A {
fun onlyB() = 29
}
Вы можете определить функцию
val fb: (B) -> Int = { it.onlyB() }
val fa: (A) -> Int = fb // ERROR
Функция fb
не сможет работать с классом A
, поскольку A
не имеет функции onlyB()
. Как следствие, вам не разрешено преобразовывать его в тип функции, который принимает A
параметров.
Эта концепция называется Контравариантность , что означает, что входные параметры могут быть ограничены только путем превращения более конкретным , а не более абстрактным. Итак, работает обратное направление:
val fa: (A) -> Int = { it.hashCode() }
val fb: (B) -> Int = fa // OK, every B is also an A
Напротив, для возвращаемых значений применяется концепция ковариация . Это означает, что возвращаемые значения могут стать более абстрактными , но не более конкретными:
val fInt: (B) -> Int = { it.onlyB() }
val fNum: (B) -> Number = fInt // OK, every Int is also a Number
Эти отношения могут быть использованы в общих классах с использованием ключевых слов Kotlin in
(контрвариантность) и out
(ковариантность) - см. здесь для подробного объяснения.