Как в приведенном выше фрагменте кода компилятор Kotlin узнает, что collect
в строке № 10 должен быть вызван в экземпляре flow
, в котором вызывается merge
?
Разве this
в строке № 10 не относится к CoroutineScope
, как намекнул редактор в строке № 9?
Фрагмент кода для справки
fun <T> Flow<T>.merge(other: Flow<T>): Flow<T> = channelFlow {
launch {
collect { send(it) }
}
other.collect { send(it) }
}
Я хотел прикрепить изображение, чтобы сделать ссылки «это», на которые намекает intellij, понятными.
Помните, что подсказки на вашем изображении исходят не от компилятора. Они исходят от вашего редактора.
@niting112: Я понимаю, это имеет смысл. Но код в виде текста тоже нужен, так что и сейчас все в порядке.
Разве это не строка № 10, относящаяся к CoroutineScope, как намекает компилятор в строке № 9?
Да, это правда. Но вы не используете this
, так что проблем нет. На самом деле в вашем примере три разных this
. Введите это и нажмите Ctrl+Space, чтобы открыть это всплывающее окно:
Первый из них очевиден из включающего launch
, второй — это поток, к которому применяется ваша функция merge
, а третий — объект-получатель channelFlow
лямбды.
Теперь к вашему первоначальному вопросу: как collect
узнает, какой this
следует использовать? Ответ в том, что он пробует все, начиная с самого внутреннего this
, то есть CoroutineScope
, затем используя ProducerScope
и, наконец, Flow
. Когда он впервые находит функцию с совпадающей сигнатурой, то есть имя и список параметров должны совпадать, он останавливается и использует ее. В противном случае он продолжает поиск другого объекта-приемника для collect
и отображает ошибку, если ни один не найден.
Если бы вы объявили соответствующую функцию collect
где-то еще в иерархии типов вашей функции merge
(если она является частью класса) или если бы она была определена на уровне файла, эта функция сбора была бы даже предпочтительнее всех остальных.
Пожалуйста, вставляйте весь код в виде текста, а не скриншотов. Затем мы можем легко скопировать его в наши IDE и опробовать на себе.