Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Что такое функция расширения (Extension Function)?
Функция расширения — это один из самых мощных и элегантных инструментов в Kotlin. Она позволяет добавлять новые функции к существующим классам без наследования и без изменения исходного кода. Это ключевая особенность Kotlin, которая делает код более чистым и читаемым.
Базовый синтаксис
Синтаксис: fun ИмяКласса.имяФункции() { ... }
// Добавляем функцию к классу String
fun String.isValidEmail(): Boolean {
return this.contains("@") && this.contains(".")
}
// Использование:
val email = "user@example.com"
if (email.isValidEmail()) {
println("Valid email")
}
Как это работает?
Receiver Object — объект, на котором вызывается функция:
fun String.addPrefix(prefix: String): String {
// this — это receiver object (объект String)
return prefix + this
}
val result = "World".addPrefix("Hello ") // "Hello World"
Функция расширения — это статическая функция с первым параметром:
// Kotlin код:
fun String.uppercase() = this.toUpperCase()
// Компилируется в (Java bytecode):
public static String uppercase(String $receiver) {
return $receiver.toUpperCase();
}
Примеры функций расширения
Для String:
fun String.isNumeric(): Boolean {
return this.all { it.isDigit() }
}
fun String.capitalizeFirstLetter(): String {
return if (this.isEmpty()) this else this[0].uppercase() + this.substring(1)
}
val str = "android"
println(str.isNumeric()) // false
println(str.capitalizeFirstLetter()) // "Android"
Для Collections:
fun <T> List<T>.secondOrNull(): T? {
return if (this.size > 1) this[1] else null
}
fun <T> List<T>.filterNotNull(): List<T> {
return this.filter { it != null }
}
val list = listOf(1, 2, 3, null)
println(list.secondOrNull()) // 2
Для View (Android):
fun View.show() {
this.visibility = View.VISIBLE
}
fun View.hide() {
this.visibility = View.GONE
}
fun View.setClickListener(action: () -> Unit) {
this.setOnClickListener { action() }
}
// Использование:
button.show()
button.setClickListener {
Log.d("Button", "Clicked")
}
Extension Properties — свойства расширения
Можно добавлять не только функции, но и свойства:
val String.firstCharacter: Char?
get() = this.firstOrNull()
val <T> List<T>.middle: T?
get() = if (this.size > 0) this[this.size / 2] else null
val str = "Kotlin"
println(str.firstCharacter) // K
val list = listOf(1, 2, 3, 4, 5)
println(list.middle) // 3
Инфиксные функции расширения
Можно создавать функции расширения в инфиксной нотации:
infix fun String.repeat(times: Int): String {
return this.repeat(times)
}
val result = "Ha" repeat 3 // "HaHaHa"
infix fun <T> List<T>.join(other: List<T>): List<T> {
return this + other
}
val merged = listOf(1, 2) join listOf(3, 4) // [1, 2, 3, 4]
Область видимости
Локальные функции расширения:
fun processData(data: String) {
// Видна только внутри этой функции
fun String.isPalindrome(): Boolean {
return this == this.reversed()
}
println(data.isPalindrome())
}
На уровне файла:
// StringUtils.kt
fun String.toTitleCase(): String {
return this.split(" ").joinToString(" ") {
it.capitalizeFirstLetter()
}
}
// Видна везде после импорта
// import com.example.toTitleCase
Функции расширения на null
fun String?.isNullOrBlank(): Boolean {
return this == null || this.isBlank()
}
val nullable: String? = null
println(nullable.isNullOrBlank()) // true
Практические примеры для Android
Работа с SharedPreferences:
fun SharedPreferences.putString(key: String, value: String) {
this.edit().putString(key, value).apply()
}
sharedPref.putString("user_name", "John")
Работа с Context:
fun Context.showToast(message: String) {
Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
}
context.showToast("Hello, Android!")
DP в пиксели:
fun Int.dpToPx(context: Context): Int {
return (this * context.resources.displayMetrics.density).toInt()
}
val margin = 16.dpToPx(context)
Приоритет разрешения
Если существует оригинальная функция и функция расширения с одинаковым названием — оригинальная функция имеет приоритет:
fun String.length(): Int = 999 // функция расширения
println("Hello".length()) // 5 (оригинальное свойство)
Преимущества и недостатки
Преимущества:
- Читаемый и интуитивный код
- Избегаем наследования и wrapper классов
- Работает с final классами
- Типобезопасность
- Работает как методы класса (IDE помогает с автодополнением)
Недостатки:
- Только доступ к публичному API
- Нельзя добавить новое состояние
- Нельзя переопределить функцию расширения (как виртуальный метод)
Функции расширения — фундаментальная часть Kotlin-way разработки, которая делает код более выразительным и удобным для чтения.