Что такое Лямбда с приемником?

Что такое Лямбда с приемником в Котлине, а у нас есть функции расширения?

Две приведенные ниже функции выполняют одни и те же вещи, однако первый из них более читабельный и короткий:

fun main(args: Array<String>) { println("123".represents(123)) println(123.represents("123")) } fun String.represents(another: Int) = toIntOrNull() == another val represents: Int.(String) -> Boolean = {this == it.toIntOrNull()} 

Lambdas с приемниками в основном точно такие же, как функции расширения, они просто могут быть сохранены в свойствах и переданы функциям. Этот вопрос по существу такой же, как «Какова цель лямбда, когда у нас есть функции?». Ответ очень похож: он позволяет вам быстро создавать анонимные функции расширения в любом месте вашего кода.

Для этого есть много хороших примеров использования (особенно в DSL ), но я приведу здесь один простой пример.

Например, предположим, что у вас есть такая функция:

 fun buildString(actions: StringBuilder.() -> Unit): String { val builder = StringBuilder() builder.acitons() return builder.build() } 

Вызов этой функции выглядит следующим образом:

 val str = buildString { append("Hello") append(" ") append("world") } 

Есть пара интересных вещей, которые позволяют:

  • Внутри лямбды вы переходите к buildString в buildString вы находитесь в новой области, у вас есть новые методы и свойства, доступные для использования. В этом конкретном случае вы можете использовать методы типа StringBuilder без необходимости их вызова на любом экземпляре.
  • Фактический экземпляр StringBuilder эти вызовы функций будут выполняться, не управляется вами – это до внутренней реализации функции для ее создания и вызова вашей функции расширения на нем.
  • Из предыдущей точки следует, что эта функция могла бы сделать гораздо больше, чем просто вызвать функцию, которую вы передали ей один раз – она ​​могла вызывать ее несколько раз, в разных экземплярах StringBuilder , хранить ее для последующего использования и т. Д.