Extension функции
Расширения - функционал, который позволяет к уже имеющемуся классу добавить какую-либо функциональность таким образом, что мы можем взять объект класса и вызвать его.
Можем добавить в любой тип, в том числе и финальный свои собственные функции.
Расширяем функцию своей реализацией. Например на вывод последнего символа.
fun String.lastCharOf(): Char = get(length - 1) fun main() { println("Java".lastCharOf()) } ПРИМЕР2: fun List<String>.getFirstElement(): String = get(0) fun main() { println(arrayListOf("str1", "str2", "str3").getFirstElement()) }
Можно расширить любой тип, который у нас имеется.
fun main() { val age = 3 val name = "" // if (name.isNotEmpty()) { // println("Enoty") // } // используется много разных проверок - может быть и более 100 // если надо поменять значение - то придётся менять у всех // if (age in 6..100) { // println("Valid 1") // } //Можем заменить на такую функцию // if (age.isAgeValid()) { // println("Valid 2") // } // // if (age.isAgeValid()) { // println("Valid 3") // } println(22.simpleNumber()) } //fun isAgeValid(age: Int) = age in 6..100 //Мы можем написать Extension функцию fun Int.isAgeValid() = this in 6..100 //Функция, определяющая положительное ли число fun Int.isPositive() = this >= 0 fun Int.simpleNumber(): Boolean { if (this <= 3) return true for (i in 2 until this) { if (this % i == 0) return false } return true }
ВАЖНЫЕ ТЕЗИСЫ:
- Расширения е обязательно могут быть глобальными. Более того их зачастую используют внутри класса и делают приватными. Не обязательно функции расширения делать общедоступными.
- Реализованы, чтобы уйти от процедурного стиля программирования к функциональному (т.е. когда так - ".func")
ЧАСТЬ 2
fun main() { val list = listOf<Int>() myWith(list) { sum() average() } val str = "ATATAT" myWith(str) { println(uppercase(Locale.getDefault())) } } //Параметризация. Дженерики- T - в качестве пааметра. // Добавляем параметры при объявлении функции. T - принимаемое значение, R - возвращаемое inline fun<T, R> myWith(obj: T, operation: T.() -> R) : R { return obj.operation() } //Создали функцию MyWith, коотрая принимает в качестве 1го параметра какой-то объект, //в качестве второго параметра какое-то действие, которое будем делать с этим объектом //Попробуем сами написать такую же функцию //Принимает в качестве параметра list а вторым параметром принимает функцию. // Т.к. функция расширяет класс list то мы можем обращаться ко бъекту листа через лист //fun myWith(list: List<Int>, operation: List<Int>.() -> Unit) { // list.operation() //} // ////Перегрузим функцию, чтобы можно было подставлять и тсрооку тоже //fun myWith(string: String, operation: String.() -> Unit) { // string.operation() //} //Что длеать если нужно выбрать другой тип. Множно написать много перегрузок, но этот вариант неверный. //Можно указать родительский класс //fun myWith(obj: Any, operation: Any.() -> Unit) { // obj.operation() //}
Приведение типов + пример расширения
fun main() { println(int.print()) } fun Any.print() : String = when(this) { is Int -> "Int: ${this.toString()}" is String -> "String: $this" else -> "Don't know: ${this.toString()}" }