Рубрики
Без рубрики

Давайте Также Применим Функции Run With Kotlin Scope

В Kotlin функции области видимости позволяют выполнять функцию, то есть блок кода, в контексте объекта. Они позволяют вам по-другому структурировать свой код, повышая читаемость. Помеченный как kotlin, java, функциональный.

В Kotlin функции области видимости позволяют выполнять функцию, то есть блок кода, в контексте объекта. Затем объект становится доступным в этой временной области без использования имени. Хотя все, что вы делаете с функциями области видимости, можно сделать и без них, они позволяют вам структурировать свой код по-другому. Их использование может повысить удобочитаемость и сделать ваш код более кратким.

Стандартная библиотека Kotlin предлагает четыре различных типа функций области видимости, которые можно классифицировать по тому, как они ссылаются на объект контекста и возвращаемое ими значение. Функция области видимости либо ссылается на объект контекста как аргумент функции , либо как приемник функции . Возвращаемым значением функции области видимости является либо результат функции , либо объект контекста .

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

Возвращает: Результат функции позволять бежать, с
Возвращает: Контекстный объект тоже применять

Разница между run и с заключается только в том, как они называются. В то время как все остальные функции области видимости реализованы как функции расширения, with является обычной функцией.

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

Kotlin позволяет обрабатывать функции как значения. Это означает, что вы можете передавать функции в качестве аргументов другим функциям. Используя оператор :: , вы можете преобразовать метод в значение функции. Чтобы повысить удобочитаемость, последний аргумент функции можно поместить вне списка аргументов.

Следующий пример иллюстрирует, как это сделать, определяя функцию более высокого порядка combine , которая принимает аргумент функции f . Мы вызываем его с помощью метода plus из класса Internet и с помощью анонимного литерала функции как внутри, так и за пределами списка аргументов:

// Apply function argument f to integers a and b
fun combine(a: Int, b: Int, f: (Int, Int) -> Int): Int = f(a, b)

// Using the plus method as a function value
combine(1, 2, Int::plus)

// Passing a function literal
combine(1, 2, { a, b ->
    val x = a + b
    x + 100
})

// Passing it outside of the argument list
combine(1, 2) { a, b ->
    val x = a + b
    x + 100
}

Функции расширения – это способ расширения существующих классов или интерфейсов, которые не обязательно находятся под вашим контролем. Определение функции расширения для класса позволяет вызывать этот метод для экземпляров этого класса, как если бы он был частью исходного определения класса.

В следующем примере определяется функция расширения на Int для возврата абсолютного значения:

fun Int.abs() = if (this < 0) -this else this

(-5).abs() // 5

Литералы функций с receiver аналогичны функциям расширения, поскольку объект receiver доступен внутри функции через this . Следующий фрагмент кода определяет функцию расширения, как и раньше, но на этот раз как литерал функции с получателем:

val abs: Int.() -> Int = { if (this < 0) -this else this }

(-5).abs() // 5

Распространенным вариантом использования функциональных литералов с приемниками являются типобезопасные конструкторы . Теперь, когда мы рассмотрели основы, давайте рассмотрим пять функций области действия по отдельности.

Позволь

Функция let scope делает объект контекста доступным в качестве аргумента функции и возвращает результат функции. Типичным вариантом использования является применение безопасных для нуля преобразований к значениям.

val x: Int? = null

// null-safe transformation without let
val y1 = if (x != null) x + 1 else null
val y2 = if (y1 != null) y1 / 2 else null

// null-safe transformation with let
val z1 = x?.let { it + 1 }
val z2 = z1?.let { it / 2 }

Также

Функция apply scope делает объект контекста доступным в качестве аргумента функции и возвращает объект контекста. Это может быть использовано, когда вы вычисляете возвращаемое значение внутри функции, а затем хотите применить к нему какой-либо побочный эффект, прежде чем возвращать его.

// assign, print, return
fun computeNormal(): String {
    val result = "result"
    println(result)
    return result
}

// return and also print
fun computeAlso(): String =
    "result".also(::println)

Применять

Функция apply scope делает объект контекста доступным в качестве получателя и возвращает объект контекста. Это делает его очень полезным для “специальных разработчиков” изменяемых объектов, таких как Java Beans.

// Java Bean representing a person
public class PersonBean {
    private String firstName;
    private String lastName;
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
    public String getFirstName() {
        return firstName;
    }
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
    public String getLastName() {
        return lastName;
    }
}
// Initialization the traditional way
val p1 = PersonBean()
p1.firstName = "Frank"
p1.lastName = "Rosner"

// Initialization using apply
val p2 = PersonBean().apply {
    firstName = "Frank"
    lastName = "Rosner"
}

Бежать и с

Функция run scope делает объект контекста доступным в качестве получателя и возвращает результат функции. Его можно использовать как с приемником, так и без него. При использовании его без приемника вы можете вычислить выражение, используя переменные с локальной областью действия. Используя приемник, run может быть вызван для любого объекта, например объекта подключения.

// compute result as block result
val result = run {
    val x = 5
    val y = x + 3
    y - 4
}

// compute result with receiver
val result2 = "text".run {
    val tail = substring(1)
    tail.toUpperCase()
}

Функция with работает точно так же, как run но реализован как обычная функция, а не как функция расширения.

val result3 = with("text") {
    val tail = substring(1)
    tail.toUpperCase()
}

В этом посте мы узнали о функциях области видимости let , также , применить , выполнить и с помощью . Они отличаются тем, как они ссылаются на объект контекста и возвращаемое ими значение. В сочетании с концепциями аргументов функций, функций расширения и приемников функции области видимости являются полезным инструментом для создания более читаемого кода.

Что вы думаете о функциях области видимости? Вы когда-нибудь использовали их в одном из своих проектов? Можете ли вы вспомнить, какой из них использовать, когда? Дайте мне знать ваши мысли в комментариях!

Оригинал: “https://dev.to/frosnerd/let-s-also-apply-run-with-kotlin-scope-functions-1ci4”