Extension Functions

https://kotlinlang.org/docs/extensions.html

Extension Functions

Kotlin позволяет расширять класс или интерфейс новой функциональностью, не наследуясь от него и не используя шаблоны проектирования. Для того, чтобы объявить функцию-расширение, нужно указать в качестве префикса расширяемый тип. Расширения вычисляются статически. Расширения на самом деле не проводят никаких модификаций с классами, которые они расширяют. Объявляя расширение, вы создаёте новую функцию, а не новый член класса.

• как расширения поддерживаются функции и свойства.

• под капотом статическая функция Java, в качестве параметра - объект расширяемого типа.

val Int.toHexColor: String
    get() = String.format("#%06X", 0xFFFFFF and this)

fun <T> MutableList<T>.swap(index1: Int, index2: Int) {
    val tmp = this[index1]
    this[index1] = this[index2]
    this[index2] = tmp
}
interface IAction {
    fun someA(): Int
    fun someB(): Int
}

fun IAction.sum(): Int {
    return someA() + someB()
}

Ограничения

Не могут изменить поведение класса

Extension-функции не могут изменять внутреннее состояние класса или его поведение, они лишь добавляют новые методы. Все изменения доступны только на уровне использования функции и не влияют на сам класс.

// Не может изменить внутреннее состояние класса
fun String.isEmpty(): Boolean {
    return this.length == 0
}

Не могут быть заменены (override)

Extension-функции не могут переопределять методы класса. Они действуют как статические методы, которые “расширяют” класс, но не изменяют его фактическую реализацию.

open class Base {
    open fun doSomething() {
        println("Base")
    }
}

fun Base.doSomething() {
    println("Extension")
}

// Вызовет метод класса, а не extension-функцию
val base = Base()
base.doSomething() // Выведет "Base"

Не могут изменять существующие методы

Extension-функции не могут изменять существующие методы класса или изменять их видимость. Они могут только добавить новые методы или функции, но не могут изменить поведение уже существующих.

// Можно только добавить новый метод
fun String.customMethod() {
    println("Custom method")
}

// Не влияет на существующие методы String
"Hello".customMethod() // Выведет "Custom method"

Не поддерживают полиморфизм

Extension-функции не поддерживают полиморфизм и не могут быть использованы для полиморфного вызова. Если в иерархии классов определены extension-функции, они не могут переопределяться в подклассах.

open class Animal
class Dog: Animal()

fun Animal.makeSound() {
    println("Animal sound")
}

fun Dog.makeSound() {
    println("Bark")
}

val animal: Animal = Dog()
animal.makeSound() // Выведет "Animal sound"

Не могут быть вызваны через super

Extension-функции не могут быть вызваны через ключевое слово super, так как они не являются частью класса, а представляют собой статические методы.

open class Base {
    open fun print() {
        println("Base")
    }
}

fun Base.print() {
    println("Extension")
}

class Derived: Base() {
    override fun print() {
        super.print() // Вызовет метод Base, а не extension-функцию
    }
}

Не поддерживают доступ к private методам

Extension-функции не могут обращаться к private свойствам класса, к которому они относятся. Они могут взаимодействовать только с public членами класса.

class MyClass {
    private fun privateMethod() {}
}

fun MyClass.accessPrivate() {
    // Не может обратиться к privateMethod()
}
Kotlin Extension Functions. Вопросы на собесе
  1. Что такое extension-функции в Kotlin и зачем они нужны?
  1. Как extension-функции выглядят в Java?
  1. Какие ограничения есть у extension-функций?
  1. Что будет если сигнатура extension-функции совпадет с внутренней функцией класса?

    Вызовется внутренняя функция, компилятор подсветит что имя занято.