Extension функции

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()}"
}


Report Page