Ответ 1
Они имеют только синтаксическую разницу, 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
body.
Различия в использовании функций обусловлены тем, что 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"