Использование неявной переменной в литерал функции - PullRequest
0 голосов
/ 08 мая 2019

Я начал читать учебник по Котлину.Я остановился на функциональных литералах.Здесь у меня есть код:

val printMessage = { message: String -> println(message) }
printMessage("hello")
printMessage("world")

Затем у меня есть информация, что я могу опустить тип параметра:

{ message -> println(message) }

И теперь у меня есть следующий шаг:

"На самом деле, у Kotlin есть более хитрый трюк. Если есть только один параметр и тип может быть определен, то компилятор позволит нам полностью опустить параметр. В этом случае он делает неявную переменную доступной:

{println(it)}

А теперь после использования этого кода я получаю ошибку «неразрешенная ссылка: это» и «слишком много аргументов для публичного оператора fun invoke (): ???определены в kotlin.Function () ":

val printMessage = {println(it)}
printMessage("print something")

Мой вопрос заключается в том, как использовать неявную переменную в литерале функции одного параметра?

Ответы [ 2 ]

3 голосов
/ 08 мая 2019

Вы всегда должны предоставлять всю информацию обо всех общих параметрах. Если вы хотите его опустить, он должен быть доступным для какой-то другой части кода. Единственная информация, которую вы предоставляете, - это то, что вы хотите, чтобы printMessage была лямбда-выражением. Таким образом, предполагается, что он имеет тип ()->Unit. Это потому, что вы не объявляете параметр для самой лямбды. Поэтому неявный параметр it не может использоваться.

val printMessage = { it: String -> println(it) }
val printMessage: (String)->Unit = { println(it) }

Проще говоря: если вы находитесь внутри лямбды с одним параметром, в качестве имени этого параметра может использоваться неявное it, но ссылка с именем it в теле лямбды не объявляет единственный параметр .

3 голосов
/ 08 мая 2019

См. Документацию Kotlin , в частности там, где написано:

Если компилятор может сам определить сигнатуру, это не объявить единственный параметр и пропустить ->. Параметр будет неявно объявлено под именем it.

В вашем случае компилятор (по крайней мере, до текущей версии 1.3.31) не может сам определить сигнатуру:

val printMessage = {println(it)}

Но если вы дадите переменной printMessage явный тип, она будет работать:

val printMessage: (String) -> Unit = { println(it) }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...