Упростите функцию Kotlin с помощью лямбды

У меня есть эта функция в классе FooClass:

fun foo(id: Int, listener: Listener<JsonElement>) {
    enqueue(listener, apiService.getFoo(id))
}

Это интерфейс:

interface Listener<T> {
    fun onSuccess(result: T?)

    fun onFailure()
}

Когда я его вызываю, я делаю так:

FooClass().foo(id, object : FooClass.Listener<JsonElement> {
    override fun onSuccess(result: JsonElement?) {}
    override fun onFailure() {}
})

Я хочу сделать лямбду для упрощения при вызове. Что-то вроде этого:

fun foo {id ->
    // Perform onSuccess
    // Perform onFailure
}

Я знаю, что это элементарно, но я запутался ... :-(

Большое спасибо за помощь.

Покажите, пожалуйста, определение Listener<T>.

miensol 29.05.2018 13:34
interface Listener<T> { fun onSuccess(result: T?) fun onFailure() }
Gabi Moreno 29.05.2018 14:00
Сортировка hashmap по значениям
Сортировка hashmap по значениям
На Leetcode я решал задачу с хэшмапой и подумал, что мне нужно отсортировать хэшмапу по значениям.
3
2
202
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Для этого вам понадобится несколько уловок.

typealias SuccessCallback<T> = (T?) -> Unit
typealias FailureCallback = () -> Unit

inline fun FooClass.foo(id: Int, crossinline success: SuccessCallback<JsonElement?>, crossinline failure: FailureCallback) {
    foo(id, object: FooClass.Listener<JsonElement> {
        override fun onSuccess(result: JsonElement?) = success(result)
        override fun onFailure() = failure()
    })
}

Теперь вы можете вызвать

FooClass().foo(id, 
    success = { result: JsonElement? -> 
        ... 
    }, 
    failure = { 
    }
)

Технически, если у вас есть FooClass, то суть в том, что вам нужно иметь возможность предоставлять две отдельные лямбды, а не только одного слушателя. Но если у вас нет FooClass, тогда вы должен сможете использовать эту функцию расширения и можете в значительной степени использовать ее где угодно. typealiases должен быть верхнего уровня внутри файла, но вне класса. Они также могут быть private. Если функция верхнего уровня, вы можете легко импортировать ее.

EpicPandaForce 29.05.2018 14:04

Спасибо за отличное объяснение :-). У меня эта ошибка внутри развлечения: object is not abstract and does not implement abstract member. Required: Int, Found: <T>

Gabi Moreno 29.05.2018 14:21

Я был так сосредоточен на crossinline, что забыл добавить параметр id: Int. Фиксированный.

EpicPandaForce 29.05.2018 14:23

У меня есть Type mismatch ... Required FooClass.Listener<JsonElement>, но Found: <T>. Обновил вопрос ... Возможно интерфейс понадобился.

Gabi Moreno 29.05.2018 16:11

Что ж ... в любом случае, я нашел верное решение, спасибо вам. Я собираюсь это написать. :-)

Gabi Moreno 29.05.2018 17:04

Мне нужно было вернуться домой и попробовать, и да, мне действительно пришлось удалить материал T. Хотя это было довольно близко, я думаю, в вашем ответе не хватает перекрестных строк. Crossinline должен улучшить байт-код, afaik.

EpicPandaForce 30.05.2018 02:08

Да, лучше и очень красиво :-). Я собираюсь выразить это как правильный ответ.

Gabi Moreno 30.05.2018 11:45

Благодаря @EpicPandaForce я нашел решение. Вот это:

fun foo(id: Int, success: (JsonElement?) -> Unit, error: () -> Unit) {
    enqueue(apiService.getFoo(id), object : Listener<JsonElement> {
        override fun onSuccess(result: JsonElement?) = success(result)

        override fun onFailure() = error()
    })
}

Я изменил порядок параметров наenqueueфункция, чтобы быть более читаемым.

Вызвать функцию очень просто:

    FooClass().foo(id,
            success = { result ->
                // Handle success result
            },
            error = {
                // Handle error
            }
    )

Другие вопросы по теме