Котлин о прохождении лямбды как собственности - PullRequest
0 голосов
/ 06 марта 2019

Я не совсем понимаю, стоит ли писать код в следующих 2 случаях:

class TestA {
    private val foo: Boolean by lazy {
        // Here is logic that return true or false
    }  
    Case 1:
    fun main() {  
        TestB({foo})
    }
    Case 2:
    fun main() {
        TestB(foo)
    }

}
Case 1:
class TestB(private val isFoo: () -> Boolean ) {
    fun checkFoo(): Boolean {
        return isFoo.invoke()
    }
}

Case 2:
class TestB(private val isFoo: Boolean ) {
    fun checkFoo(): Boolean {
        return isFoo
    }
}

Когда мне следует использовать случай 1 или случай 2?
Кстати, пожалуйста, дайте мне знать, как вызывается () метод работы?

Ответы [ 2 ]

2 голосов
/ 06 марта 2019

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

Что касается вашего вопроса относительно invoke: у Kotlin есть ряд функций, которые работают "по соглашению", например, rangeTo, equals,contains, compareTo, операторы индекса, а также invoke.Узнайте о соглашениях здесь .

Теперь, когда класс предоставляет оператор invoke, вы можете вызывать экземпляры этого класса, как если бы они были функциями:

class InvokeMe(){
    operator fun invoke(value: Int) = println("invoked with $value")
}

val obj = InvokeMe()
//both are compiled to the same code
obj(10)
obj.invoke(5)  

Поскольку каждая лямбда компилируется в Function экземпляр (см. kotlin.jvm.functions), который поставляется с реализацией invoke, вы можете вызывать лямбда-выражения, как показано выше, то есть, используя lambda(args) или lambda.invoke(args)

1 голос
/ 06 марта 2019

.invoke() просто вызовет вашу лямбду и выдаст ваш результат, так же как вызов функции.

Что касается того, когда вы должны передать лямбда или фактическое значение, оно очень зависит.

Лично я бы предложил использовать лямбда-выражения в очень специфических ситуациях, чрезмерное их использование может сделать ваш код очень запутанным и трудным для рефакторинга. Если вы просто хотите, чтобы результат был передан в функцию, просто передайте фактическое значение. Не заставляйте кого-либо звонить .invoke().

Но несколько хороших примеров для лямбды - это обратные вызовы или onClickListeners.

// A login network request with a lambda handling the result.
fun login( username: String, password: String, onResult: (Result) -> Unit ) {
    // do some network call, and return a Result.
}

// note: if the last param is a lambda, you can simply move it outside the function call like this.
login( username, password ) { result ->
    // use the result of the network request.
}

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...