Найти в Дзене

🐾 "apply", "also", "run", "let", "with" — зачем нам всё это?

Сегодня разберём "любимую" тему всех разработчиков — scope-функции. Таких функций вроде бы много, все похожи, но на самом деле у каждой есть своя роль — как у игрушек у котика. Мячик — чтобы гонять, коробка — чтобы сидеть, мышка — чтобы охотиться. Так же и с apply, also, run, let, with. Scope-функции — это такие функции, которые позволяют выполнить блок кода в контексте объекта. Они помогают: А теперь человеческим языком. Представим, что у нас есть котик по имени Барсик. И мы хотим: Вот scope-функции как раз нужны, чтобы не писать “Барсик. Барсик. Барсик…” по сто раз, а просто один раз сказать: «Сейчас мы говорим про Барсика — и вот что мы с ним делаем». Все эти функции — inline (тело функции вставляется в место вызова на этапе компиляции). То есть они не вносят накладных расходов и не создают лишних объектов при компиляции. Главное — не устраивать вложенный ад: Scope-функции — это способ временно погрузиться в объект: что-то с ним сделать, изменить или извлечь результат. Главное — дел
Оглавление

Сегодня разберём "любимую" тему всех разработчиков — scope-функции. Таких функций вроде бы много, все похожи, но на самом деле у каждой есть своя роль — как у игрушек у котика. Мячик — чтобы гонять, коробка — чтобы сидеть, мышка — чтобы охотиться. Так же и с apply, also, run, let, with.

📊 Что такое scope-функции?

Scope-функции — это такие функции, которые позволяют выполнить блок кода в контексте объекта. Они помогают:

  • не повторять имя объекта,
  • улучшить читаемость,
  • выразить намерение: инициализация, побочные эффекты, обработка nullable и т.д.

А теперь человеческим языком. Представим, что у нас есть котик по имени Барсик. И мы хотим:

  • дать ему имя, цвет, пушистость — и всё это в одном месте;
  • проверить, есть ли у него игрушка, и если есть — поиграть;
  • записать в блокнот, что он сделал сегодня.

Вот scope-функции как раз нужны, чтобы не писать “Барсик. Барсик. Барсик…” по сто раз, а просто один раз сказать:

«Сейчас мы говорим про Барсика — и вот что мы с ним делаем».

🐈 apply: кот сам себя причесал

  • Контекст: this
  • Возвращает сам объект
  • Идеально для конфигурации или билдеров
  • Кот приводит себя в порядок — меняется сам, никого не трогает.

🐾 also: кот получил игрушку и сообщил об этом

-2
  • Контекст: it
  • Возвращает тот же объект
  • Удобно для логов, проверок, отладочных действий
  • Кот комментирует происходящее, но сам не меняется

🏡 run: кот залез в коробку и поразмышлял

-3
  • Контекст: this
  • Возвращает результат вычислений
  • Когда использовать: когда нам нужен не сам объект, а результат его анализа — например, составить описание, проверить условие, рассчитать что-то.
  • Кот залез в коробку, поразмышлял — и выдал результат. Сам он при этом остался в коробке. Например: "Да, у меня осталась одна мышка и две сосиски. Жить можно."

🧂 let: кот нашёл игрушку и поиграл

-4
  • Контекст: it
  • Возвращает результат
  • Лучше всего работает с nullable-объектами
  • Когда использовать: безопасно работать с объектом, который может быть null, или когда нужно сделать преобразование. Если объекта нет — let просто не вызывается. Кот даже не встаёт.

💫 with: ты пришёл к коту в гости

-5
  • Контекст: this
  • Возвращает результат
  • Когда использовать: когда у тебя уже есть объект, и ты хочешь выполнить с ним несколько действий подряд, не повторяя его имя
  • Важно: это не extension-функция — ты вызываешь with(cat), а не cat.with {}

🧩 Технические тонкости (и когда НЕ стоит использовать)

  • apply — отлично подходит для настройки, как когда кот расчесывает сам себя.
    ❗️Если нам нужен не сам кот, а
    результат его размышлений — используем run, а не apply.
  • also — идеален для встраивания логов или дебага в цепочках: кот мяукнул и пошёл дальше.
    🛑
    Не пихать туда логику! Мутировать объект внутри also — как если бы кот по пути на кухню ещё и ремонт начал.
  • run — хорош, когда мы хотим внутри объекта что-то посчитать и выйти с результатом.
  • let — незаменим для nullable, но...
    ❌ cat?.let { it.kitten()?.let { ... } } — это уже кот, заблудившийся в лабиринте it.
    📉 Два let подряд — подумай, не пора ли выделить это в функцию.
  • with — удобен, когда ты уже сидишь у кота в гостях и делаешь сразу всё.
    ⚠️ Но это не extension. Его легко перепутать, и в цепочках он чужероден — как собака в кошачьем доме.

📈 Производительность

Все эти функции — inline (тело функции вставляется в место вызова на этапе компиляции). То есть они не вносят накладных расходов и не создают лишних объектов при компиляции. Главное — не устраивать вложенный ад:

-6

😼 Вывод

Scope-функции — это способ временно погрузиться в объект: что-то с ним сделать, изменить или извлечь результат. Главное — делать это осознанно:

apply — кот сам себя причесал. Меняем объект и возвращаем его.

also — кот мяукнул по дороге: логируем, но ничего не трогаем.

run — кот подумал и выдал результат: вычисляем что-то на основе объекта.

let — кот проверил, есть ли игрушка, и если есть — поиграл: работаем с nullable.

with — мы зашли к коту в гости и сразу сделали всё нужное.

-7

Дубль статей в телеграмме — https://t.me/android_junior

Мои заметки в телеграмме — https://t.me/android_junior_notes