Что такое функция расширения

Ответ

Функции расширения (extension functions) в Kotlin позволяют добавлять новые функции к существующим классам без наследования или модификации исходного кода. Они объявляются с префиксом имени класса, который расширяется.

// Пример: расширение класса String
fun String.addExclamation(): String {
    return "$this!"
}

// Использование
val greeting = "Hello".addExclamation() // "Hello!"

Особенности:

  • Не изменяют оригинальный класс
  • Доступны как обычные методы класса
  • Работают с nullable-типами (String?.)
  • Можно расширять даже классы из стандартной библиотеки или Java-классы

Ответ 18+ 🔞

А, ну слушай, вот эта штука с extension functions — это вообще пиздец как удобно, я тебе скажу. Представь, что ты купил машину, а потом тебе говорят: «А хочешь, мы тебе к ней прикрутим ништяк, чтобы она ещё и кофе варила?» И ты такой: «Ну хули нет». И вот тебе уже не надо новую машину покупать, просто приварили кофеварку к капоту, и всё, едешь и капучино себе на ходу делаешь. Примерно так это и работает.

Вот смотри, есть у тебя класс, например, String. Стандартный, из коробки. И вдруг тебе позарез понадобилось, чтобы у каждой строки был метод, который добавляет к ней восклицательный знак. Раньше пришлось бы городить какой-нибудь утилитарный класс StringUtils и писать там статический метод addExclamation(String s). А потом везде его импортить и вызывать. Скучно, неудобно, выглядит как говно.

А теперь можно сделать так, ёпта:

// Просто берёшь и говоришь: "А пусть у всех String'ов будет такой метод!"
fun String.addExclamation(): String {
    return "$this!" // this — это та самая строка, у которой метод вызвали
}

// Использование
val greeting = "Hello".addExclamation() // Получится "Hello!"

Вот и всё, блядь. Теперь у любой строки в твоём коде, в этом файле, есть метод addExclamation(). Вызываешь его, как будто он там всегда и был. Красота, да? Удивление пиздец просто.

Ну и какие там фишки, на что смотреть:

  • Не лезут в чужой огород. Они реально не меняют исходный класс. Никакого наследования, никакой магии с байткодом. Это просто синтаксический сахар, который компилятор разворачивает в тот самый статический вызов. Но выглядит-то как родной метод! Хитрая жопа, но гениальная.
  • Доступны как свои. После объявления расширения ты можешь звать этот метод ровно так же, как и все остальные методы этого класса. IDE будет его подсказывать, автодополнение работать — красота.
  • Работают даже с nullable. Вот это вообще мощь. Можешь объявить расширение для String?. И внутри функции уже проверять: если this == null, то возвращать что-то одно, а если не null — другое. Удобно для всяких преобразований или безопасных операций.
  • Расширяй кого хочешь. Да хоть ArrayList из Java, хоть Thread, хоть какой-нибудь легаси-класс из древней библиотеки. Не надо ждать, пока автор класса что-то добавит. Сам себе царь, сам себе добавляешь функционал. Главное — не переборщить, а то получится такой зоопарк, что потом сам от себя охуеешь.

Короче, вещь архиполезная. Поначалу кажется, что какая-то ерунда, но как втянешься — начинаешь везде их пихать. Только без фанатизма, а то можно такую мудню нарасширять, что потом разбираться будет страшнее, чем в дебрях чужого кода.