Ошибка:
Type mismatch.
Required: Mono<Authentication>
Found: Mono<CustomAuth!>
Ошибка создания кода:
fun example(): Mono<Authentication> {
return Mono.just("")
.map { _ -> CustomAuth() }
.onErrorReturn(CustomAuth())
}
где аутентификация взята из org.springframework.security.core, а CustomAuth:
class CustomAuth : Authentication {
// ...
}
Однако это работает, если мы добавим приведение, например.
fun example(): Mono<Authentication> {
return Mono.just("")
.map { _ -> CustomAuth() as Authentication }
.onErrorReturn(CustomAuth())
}
Зачем нужен актерский состав?





T в Mono<T> является инвариантом , аналогично тому, как ArrayList<Dog> не является подтипом ArrayList<Animal>. Все параметры типа классов, импортированных из Java, инвариантны.
Насколько мне известно, Mono<T> теоретически может быть ковариантным, потому что Mono<T> семантически является «производителем» T, а не «потребителем» T. Котлинский Flow, который имеет схожую семантику с Mono (хотя на самом деле он больше похож на Flux), действительно имеет ковариант T.
example можно объявить возвращающим Mono<out Authentication>, чтобы сделать его ковариантным,
fun example(): Mono<out Authentication> { ... }
Но это ограничивает то, что вы можете делать с возвращаемым значением. Нельзя делать example().onErrorReturn(CustomAuth()), например. Опять же, теоретически это безопасно, но поскольку Mono написан на Java, Котлин не понимает.
Что касается того, почему добавление приведения исправляет это, это потому, что приведение изменяет результат вывода типа map. Без приведения предполагается, что map возвращает Mono<CustomAuth>. При добавлении приведения предполагается, что map вернется Mono<Authentication>.
Обратите внимание, что удаление вызова onErrorReturn также разрешает эту компиляцию по той же причине. Поскольку map является последним вызовом в цепочке, вывод типа может учитывать «ожидаемый тип» (Mono<Authentication>) для вывода параметров типа map. С другой стороны, «ожидаемый тип» не может участвовать в выводе типа, когда onErrorReturn является последним вызовом в цепочке, потому что onErrorReturn вообще не является универсальным.
Вы также можете явно указать параметр типа map.
.map<Authentication> { CustomAuth() }