null или пустая лямбда как значение по умолчанию

какое решение лучше? использовать обнуляемую лямбду или передать пустую лямбду в качестве параметра по умолчанию? kotlin как-то оптимизирует пустую лямбду? или создать новый экземпляр, который ничего не делает?

class Test1(val action: () -> Unit = {})

К сожалению, я не понимаю сгенерированный байт-код. Давайте проанализируем

val test11 = Test1()

после декомпиляции дает нам

private static final Test1 test11 = new Test1((Function0)null, 1, (DefaultConstructorMarker)null);

и, наконец, когда лямбда передается примерно так

var1 = (Function0)null.INSTANCE;

edit: скрытые вопросы: как Kotlin обрабатывает пустую лямбду как значение по умолчанию?


person Paweł Byszewski    schedule 05.08.2016    source источник
comment
Какое решение лучше, зависит от того, чего вы пытаетесь достичь или для чего оптимизировать?   -  person miensol    schedule 05.08.2016
comment
Не хотелось бы иметь ненужные, пустые экземпляры. Я знаю, что самое простое решение - иметь лямбду, допускающую значение NULL, но это подразумевает уродливые конструкции action?.invoke().   -  person Paweł Byszewski    schedule 05.08.2016
comment
@PawełByszewski, что вас беспокоит по поводу class Test1(val action: () -> Unit = {})?   -  person ruX    schedule 05.08.2016
comment
Вы спросили мнение между двумя субъективными ответами. Поэтому ответ на ваш вопрос: используйте null, если вам нравится иметь дело с нулями, или используйте empty, если вы хотите иметь пустое поведение, когда значение отсутствует. Тот же вопрос можно задать о том, должен ли я иметь нулевой список или пустой список? и ответ тот же, это зависит от вас   -  person Jayson Minard    schedule 05.08.2016
comment
Оба решения кажутся мне вонючими. Почему бы не иметь два отдельных типа: один с действием и один без? Возможно, вам придется использовать наследование и/или делегирование для повторного использования некоторого кода. Вы можете даже сделать action абстрактной функцией вместо свойства. Я подозреваю, что ваш код будет чище.   -  person mfulton26    schedule 05.08.2016
comment
Вы можете иметь право, но я полагаю, что есть случаи, когда такой подход разумен. Например, DSL или пример построителя диалоговых окон, которые следуют шаблону хорошо известной структуры. В любом случае, вопросы, как работает Kotlin, все еще ждут ответа.   -  person Paweł Byszewski    schedule 05.08.2016


Ответы (2)


Определенно более идиоматично передавать пустую лямбду, а не ноль в качестве значения по умолчанию для лямбда-параметра.

Декомпилятор, используемый в IntelliJ IDEA, не всегда хорошо обрабатывает байт-код Kotlin, поэтому то, что вы видите в его выводе в этом случае, не отражает того, что происходит на самом деле. На самом деле пустая лямбда будет скомпилирована в одноэлементный вложенный класс, реализующий соответствующий интерфейс FunctionN с пустым телом, а одноэлементный экземпляр будет использоваться в качестве значения по умолчанию.

Дополнительные сведения о том, как параметры по умолчанию реализованы на Котлине.

person yole    schedule 05.08.2016
comment
Как проверить, пуста ли лямбда? - person Sunstrike; 21.08.2017
comment
@Sunstrike Нет способа сделать это. Как вы думаете, зачем вам это нужно? - person yole; 21.08.2017
comment
Открыл вопрос stackoverflow.com/ вопросов/45799825/ и, вероятно, получил решение - person Sunstrike; 21.08.2017
comment
Kotlin новичок здесь. Глупо ли устанавливать пустую лямбду (переменную, содержащую лямбду) только для того, чтобы освободить ресурсы после того, как я закончу с лямбдой? - person Sevastyan Savanyuk; 25.09.2017
comment
Определенно более идиоматично передавать пустую лямбду - я не согласен. Поскольку в kotlin обнуляемость является гражданином первого класса и явным указанием на отсутствующее значение, я бы передал null в качестве аргумента по умолчанию. У него также есть преимущество в том, что его можно легко проверить и обработать, и вы не ожидаете, что лямбда сделает что-то полезное, особенно для лямбда-выражений с возвращаемым значением. - person Mathias Henze; 10.05.2020

Посмотрите последний параметр выставленной функции:

internal fun showDialog(title: String, message:String?= null, okButtonAction: () -> Unit, koButtonAction:() -> Unit = {}){ //do things.....}
person Catluc    schedule 13.06.2018