Как стать автором
Обновить

Комментарии 13

Зачем делать свойство-расширение с типом лямбды? Почему не просто метод-расширение?
В этом случае свойство-расширение включает два пространства имен (в моем случае и View, и Data)
val Data.bindMethod_cell_2: View.() -> Unit
    get() = {
        //cell2_icon принадлежит View, icon принадлежит Data, а функция обращается к обоим свойствам без префиксов view. и data.
        cell2_icon.setImageResource(icon)
        cell2_text.setText(titleId)
    }
Ну это почти то же самое что и
fun Data.bindMethod_cell_2(view: View) {
    view.cell2_icon.setImageResource(icon)
    view.cell2_text.setText(titleId)
}

Ради чего? Избавиться от явных имён переменных? Зато усложнить само объявление функции. И теперь вместо простого метода у вас в байткоде добавится новый анонимный класс.

Какой-то перебор во всём.
Я в аннотации написал, что данная статья исключительно о языковых возможностях, никак не о стиле программирования.

По моему, вы перемудрили. Все в кучу. Там вроде и так все просто. А у вас как-то все сложно, при этом даже без дженериков. Еще с возвратом экстеншн лямды.
Вы в следующий раз спросите себя перед тем как писать код: "а нужно ли мне это?", я вот так с корутинами вляпался.

Любой функционал (а тем более такой сложный) требует отличного понимания, зачем оно нужно и почему выгодно использовать именно его. Еще раз, в этой статье (как, в прочем, и ни в какой другой статье) я никого не склоняю к определенному стилю — я показываю возможности языка.
Если цель просто иметь доступ к переменным двух классов, то чем вас не устроил «apply»?
fun Data.bindCell1(view: View) = view.apply{
    cell1_icon.setImageResource(icon)
    cell2_text.setText(titleId)
}
Всем, но тогда пример бы не получился. В аннотации я указал, что статья не стиля программирования ради, а для описания возможностей языка.
Нельзя оценить выразительность языка в полной мере, если рассматривать неудачные примеры. К сожалению, у вас в статье описанные возможности и правда используются не по назначению. Единственного apply было бы достаточно.
На самом деле apply внутри состоит из схожего метода.
@kotlin.internal.InlineOnly
public inline fun <T> T.apply(block: T.() -> Unit): T {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    block()
    return this
}

Но опять же, для наглядности написал свой.
Почти уверен, что если разобрать реализацию существующих функций, перед этим показав, как их применять, статья будет намного более полезной.
> cell2_icon.setImageResource(icon)

А только меня смущает, что из кода теперь невозможно понять к какому классу относится «icon», ко view или к data?

Если эта информация просто теряется — это не выразительность, это наоборот, обфускация. И потенциальный источник ошибок.
В Kotlin, если использовать подобные конструкции, однозначно нужно использовать преффикс (вроде cell2_ в cell2_icon) в именах элементов лайаута. Потому что как раз в них крайне легко накосячить с импортом сгенерированного обращения и получить NullPointer. Одновременно с этим он и позволяет избежать обфучкации конкретно в моем примере.
В целом, в своих проектах объединение нескольких пространств имен я практикую только в заранее безопасных вариантах — model (набор переменных) и view (набор переменных с префиксами), модель и сервис (набор методов), модель логику (набор методов вроде process_ и show_).
Объединение пространств имен, как и множественное наследование, однозначно не является рекомендуемой практикой и должно подкрепляться пониманием программиста, что и зачем он делает. Тот самый случай, когда проще совсем не значит лучше.
Именно мой пример я считаю безопасным в использовании, т.к. префиксы более я нигде не использую, кроме имен отображаемых элементов.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории