Ответ
Расширение класса (extension function) в Kotlin позволяет добавлять новые функции к существующим классам без наследования или модификации исходного кода. Это удобно для работы со сторонними библиотеками или стандартными классами.
// Пример: добавление функции для String
fun String.addExclamation(): String {
return "$this!"
}
// Использование
val greeting = "Hello".addExclamation() // "Hello!"
Особенности:
- Расширения статически разрешаются (не виртуальны)
- Не имеют доступа к приватным членам класса
- Могут быть объявлены для nullable-типов (
String?) - Часто используются для улучшения читаемости кода (например, в DSL)
Ответ 18+ 🔞
Слушай, а вот эта штука с расширениями в Котлине — это вообще пиздец как удобно, ёпта. Представь: есть у тебя какой-нибудь стандартный класс, как этот твой String, и ты не можешь в него просто так залезть и дописать свою функцию. Раньше бы пришлось городить огород, а тут — раз, и ты ему новую фичу прилепил, как будто она там всегда и была. Ебать мои старые костыли, гениально же!
Вот смотри, самый простой пример, чтобы мозг не взорвался сходу:
// Пример: добавление функции для String
fun String.addExclamation(): String {
return "$this!"
}
// Использование
val greeting = "Hello".addExclamation() // "Hello!"
Видишь? Взяли класс String, который нам не принадлежит, и навесили на него свою собственную функцию addExclamation. И теперь любой стринг может кричать! Это же овердохуища удобно, особенно когда работаешь с какими-нибудь легаси-либами, куда тебе исходников не дают. Хочешь добавить туда какую-то свою логику — хуй с горы, делаешь extension и живёшь спокойно.
Но тут, чувак, есть свои подводные камни, про которые надо помнить, а то потом будешь охуевать, почему не работает.
Во-первых, они разрешаются статически. Это значит, что если у тебя есть класс Animal и наследник Dog, и ты сделал extension-функцию для Animal, то она не будет виртуальной. Вызовется всегда та, что для объявленного типа переменной, а не для реального объекта. Может сбить с толку, если не знать.
Во-вторых, внутрь класса они не лезут. То есть к приватным полям или методам доступа нет, только к публичным. Так что это не полноценная замена модификации класса, а такая хитрая надстройка сверху.
В-третьих, их можно делать даже для nullable-типов! Вот это вообще мощь. Например, fun String?.safeToUpperCase(): String?. И тогда можно вызывать функцию даже на null, и она не сломается с NPE, а обработает это внутри себя. Удивление пиздец, как это иногда спасает.
И самое главное — их обожают использовать для всяких DSL (Domain Specific Language). Когда ты строишь какой-нибудь конфиг или разметку кодом, и получается почти как на родном языке. Читаемость кода взлетает до небес, волнение ебать!
Короче, инструмент архиполезный. Главное — не увлекаться и не начать расширять всё подряд, а то получится такая каша, что сам потом не разберёшься, где родные методы, а где твои костыли. Всё должно быть к месту, понимаешь?