Тип функции с различными возможными типами аргументов - PullRequest
0 голосов
/ 23 сентября 2019

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

interface SomeDataSource {
    @GET("some_url")
    suspend fun getObjects(@Path("id") userId: String): Response<A>

    @PUT("some_url")
    suspend fun updateClientFirstName(@Path("id") id: String, @Body requestA: RequestA): Response<Unit>
}
class SomeRepositoryImpl(private val someDataSource: SomeDataSource) : SomeRepository {
     override suspend fun getObjects(userId: String): List<A>? {
        return baseRequestMaker(params.., true, someDataSource::getObjects)
    }
}
suspend fun <P, T> baseRequestMaker(params: P, isShowLoader: Boolean = true, request: suspend (input: P) -> Response<T>): T? {
    if (isShowLoader) {
        BaseFragment.apiState.value = Result.Loading
    }
    return withContext(Dispatchers.IO + BaseBanqrCoroutineExceptionHandler(CoroutineExceptionHandler)) {
        val apiResponse = request(params)
        val response = apiResponse.body()
        GlobalScope.launch(Dispatchers.Main + BaseBanqrCoroutineExceptionHandler(CoroutineExceptionHandler)) {
            BaseFragment.apiState.value = Result.Success(response)
        }
        return@withContext response
    }
}

Проблема в том, что в моем запросе параметры функции могут иметь любой тип и количество, и я не могу их обернуть в объект, потому что в этом случае аннотации Retrofit, такие как @Path, @Query, @Body .., не будут работать.

1 Ответ

0 голосов
/ 23 сентября 2019

Я не уверен, что ваш вопрос достаточно ясен.Однако ..

Вы можете сделать следующее.

// the method with many arguments
fun methodManyArguments(arg1: String, arg2: Int, arg3: Boolean) {
    println("Calling methodManyArguments($arg1, $arg2, $arg3)")
}

// the method that will pass the many arguments
fun passMethod(method: (arg1: String, arg2: Int, arg3: Boolean) -> Unit) {
    method("arg1", 3, false)
}

// call the passMethod as following
passMethod(::methodManyArguments)

Синтаксис :: в Kotlin в основном говорит "не вызывать" функцию сейчас, а вместо этого взять ссылку на функциювызовите позже.Подробнее здесь

Я бы предложил объединить ваши многочисленные аргументы в класс-оболочку, известный как Шаблон параметров объекта .В основном это легче поддерживать.

Пример с вашим делом будет следующим:

// the method with many arguments
fun methodInput(input: MethodInput) {
    println("Calling methodInput($input)")
}

// the method that will pass the many arguments as ONE
fun passMethodInput(method: (MethodInput) -> Unit) {
    method(MethodInput("arg4", 6, true))
}

// the data class for the parameter object
data class MethodInput(val arg1: String, val arg2: Int, val arg3: Boolean)

//calling the passMethodInput
passMethodInput(::methodInput)

Kotlin Playground Пример для рабочего примера здесь

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