Разница между kotlin также, применить, позволить, использовать, takeIf и takeUnless в Kotlin
Я прочитал много документов Kotlin об этих пунктах. Но я не могу понять так ясно.
Какая польза от Kotlin, позволяющеготакжевзять и взять в деталях?
Мне нужен пример каждого элемента. Пожалуйста, не размещайте документацию Kotlin. Мне нужен пример в реальном времени и варианты использования этих предметов.
2 ответа
позволять
public inline fun <T, R> T.let(block: (T) -> R): R = block(this)
Возьмите получатель и передайте его функции, переданной в качестве параметра. Вернуть результат функции.
val myVar = "hello!"
myVar.let { println(it) } // Output "hello!"
Ты можешь использовать let
для нулевой проверки безопасности:
val myVar = if (Random().nextBoolean()) "hello!" else null
myVar?.let { println(it) } // Output "hello!" only if myVar is not null
также
public inline fun <T> T.also(block: (T) -> Unit): T { block(this); return this }
Выполните функцию, переданную с получателем в качестве параметра, и верните получателя.
Это как пусть, но всегда возвращает получателя, а не результат функции.
Вы можете использовать это для выполнения чего-либо на объекте.
val person = Person().also {
println("Person ${it.name} initialized!")
// Do what you want here...
}
takeIf
public inline fun <T> T.takeIf(predicate: (T) -> Boolean): T? = if (predicate(this)) this else null
Вернуть получатель, если функция (предикат) вернет true, иначе вернет null.
println(myVar.takeIf { it is Person } ?: "Not a person!")
takeUnless
public inline fun <T> T.takeUnless(predicate: (T) -> Boolean): T? = if (!predicate(this)) this else null
Такой же как takeIf
, но с предикатом поменялся местами. Если true, вернуть null, иначе вернуть получателя.
println(myVar.takeUnless { it is Person } ?: "It's a person!")
Помогите
- Вы можете легко использовать https://try.kotlinlang.org/ для тестирования. Вы можете найти примеры здесь.
- Вы можете проверить исходный код стандартной библиотеки здесь.
let
,also
,takeIf
а такжеtakeUnless
здесь
пусть, также, apply, takeIf, takeUnless являются функциями расширения в Kotlin.
Чтобы понять эти функции, вы должны понимать функции расширения и лямбда-функции в Kotlin.
Функция расширения:
Используя функцию расширения, мы можем создать функцию для класса без наследования класса.
Kotlin, подобно C# и Gosu, предоставляет возможность расширять класс новыми функциями без необходимости наследования от класса или использования любого типа шаблона проектирования, такого как Decorator. Это делается с помощью специальных объявлений, называемых расширениями. Kotlin поддерживает функции расширения и свойства расширения.
Итак, чтобы найти только цифры в String
, вы можете создать метод, как показано ниже, без наследования String
учебный класс.
fun String.isNumber(): Boolean = this.matches("[0-9]+".toRegex())
Вы можете использовать вышеуказанную функцию расширения следующим образом:
val phoneNumber = "8899665544"
println(phoneNumber.isNumber)
который печатает true
,
Лямбда-функции:
Лямбда-функции аналогичны интерфейсу в Java. Но в Kotlin лямбда-функции могут быть переданы в качестве параметра в функции.
Пример:
fun String.isNumber(block: () -> Unit): Boolean {
return if (this.matches("[0-9]+".toRegex())) {
block()
true
} else false
}
Вы можете видеть, что блок является лямбда-функцией и передается в качестве параметра. Вы можете использовать вышеуказанную функцию, как это,
val phoneNumber = "8899665544"
println(phoneNumber.isNumber {
println("Block executed")
})
Вышеуказанная функция будет печататься так,
Block executed
true
Надеюсь, теперь у вас есть представление о функциях расширения и лямбда-функции. Теперь мы можем перейти к функциям расширения одна за другой.
позволять
public inline fun <T, R> T.let(block: (T) -> R): R = block(this)
Два типа T и R используются в вышеуказанной функции.
T.let
T
может быть любой объект, как класс String. так что вы можете вызывать эту функцию с любыми объектами.
block: (T) -> R
В параметре let вы можете увидеть вышеприведенную лямбда-функцию. Также вызывающий объект передается в качестве параметра функции. Таким образом, вы можете использовать вызывающий объект класса внутри функции. тогда он возвращает R
(другой объект).
Пример:
val phoneNumber = "8899665544"
val numberAndCount: Pair<Int, Int> = phoneNumber.let { it.toInt() to it.count() }
В приведенном выше примере let принимает String в качестве параметра своей лямбда-функции и возвращает Pair в ответ.
Точно так же работает другая функция расширения.
также
public inline fun <T> T.also(block: (T) -> Unit): T { block(this); return this }
функция расширения also
принимает вызывающий класс в качестве параметра лямбда-функции и ничего не возвращает.
Пример:
val phoneNumber = "8899665544"
phoneNumber.also { number ->
println(number.contains("8"))
println(number.length)
}
применять
public inline fun <T> T.apply(block: T.() -> Unit): T { block(); return this }
То же самое, но и тот же вызывающий объект, переданный как функция, так что вы можете использовать функции и другие свойства, не вызывая его или имя параметра.
Пример:
val phoneNumber = "8899665544"
phoneNumber.apply {
println(contains("8"))
println(length)
}
В приведенном выше примере вы можете видеть функции класса String, непосредственно вызываемые внутри функции lambda.
takeIf
public inline fun <T> T.takeIf(predicate: (T) -> Boolean): T? = if (predicate(this)) this else null
Пример:
val phoneNumber = "8899665544"
val number = phoneNumber.takeIf { it.matches("[0-9]+".toRegex()) }
В приведенном выше примере number
будет иметь строку phoneNumber
только это соответствует regex
, В противном случае это будет null
,
takeUnless
public inline fun <T> T.takeUnless(predicate: (T) -> Boolean): T? = if (!predicate(this)) this else null
Это обратное восприятие.
Пример:
val phoneNumber = "8899665544"
val number = phoneNumber.takeUnless { it.matches("[0-9]+".toRegex()) }
number
будет иметь строку phoneNumber
только если не соответствует regex
, В противном случае это будет null
,