Разница между тем и запуском в Котлине

У вас есть и run с одинаковой функциональностью только с другим синтаксисом или существуют ли какие-либо существенные различия между ними и их run ?

Каков правильный путь?

 adapter.run { notifyDataSetChanged() if (activityDetails.isEmpty()) emptyText.visibility = View.VISIBLE else emptyText.visibility = View.GONE } with(adapter){ notifyDataSetChanged() if (activityDetails.isEmpty()) emptyText.visibility = View.VISIBLE else emptyText.visibility = View.GONE } 

Они имеют только синтаксическую разницу, run – это функция расширения, а with . Вот определения (в kotlin-sdlib:1.0.3 ):

 public inline fun <T, R> T.run(block: T.() -> R): R = block() // equivalent to this.block() public inline fun <T, R> with(receiver: T, block: T.() -> R): R = receiver.block() 

Поскольку run является функцией расширения, он имеет еще один неявный аргумент типа T , поэтому типы аргументов одинаковы. Тела функций также фактически одинаковы.

Их производительность также должна быть эквивалентной, поскольку оба являются inline функциями : полученный байт-код должен содержать только встроенный block .


Различия в использовании функций вызваны тем, что run является расширением.

Во-первых, run подходит для цепочки вызовов:

 foo.run { bar }.run { baz } 

Во-вторых, и что более важно, если объявленный тип переменной run функцию с той же сигнатурой, она будет вызываться вместо расширения. И run может быть затенен другим расширением. Именно так разрешаются расширения . Пример:

 class MyClass { fun <R> run(blockIgnored: MyClass.() -> R): Nothing = throw RuntimeException() } "abcdefg".run { println("x") } // prints "x" MyClass().run { println("x") } // throws RuntimeException (MyClass() as Any).run { println("x") } // prints "x" 

В нормальном случае они довольно похожи, но для переменной с T.run() лучше использовать T.run()

Например, если webview.settings имеет значение NULL, ниже будет показано

 with(webview.settings) { this?.javaScriptEnabled = true this?.databaseEnabled = true } // similarly webview.settings?.run { javaScriptEnabled = true databaseEnabled = true }