从 when 条件调用具有两种不同类型的相同函数

Call the same function with two different types from a when condition

我想知道是否可以将对存在于两种不同类型的函数的调用分组,而不必在“when”语句中创建两个分支。

例如,在我的例子中,我有这个 class 扩展名:

// File: PublisherExtensions.kt

fun <T> Mono<T>.toServiceResponse(): Mono<Response<T>> =
    this.map { r -> Response(true, r, null) }
        .onErrorResume { e -> Mono.just(Response(false, null, Response.Error(500, e.message))) }

fun <T> Flux<T>.toServiceResponse(): Mono<Response<List<T>>> =
    this.collectList()
        .map { r -> Response(true, r, null) }
        .onErrorResume { e -> Mono.just(Response(false, null, Response.Error(500, e.message))) }

我对他们使用的是这个声明:

val body = when (val value = result.returnValue) {
    is Mono<*> -> value.toServiceResponse()
    is Flux<*> -> value.toServiceResponse()
    else -> throw RuntimeException("The \"body\" should be Mono<*> or Flux<*>!")
}

虽然我想要的是:

val body = when (val value = result.returnValue) {
    is Mono<*>, is Flux<*> -> value.toServiceResponse()
    else -> throw RuntimeException("The \"body\" should be Mono<*> or Flux<*>!")
}

IDE 给我这个错误:

Unresolved reference.
None of the following candidates is applicable because of receiver type mismatch:

  • public fun Flux<TypeVariable(T)>.toServiceResponse(): Mono<Response<List<TypeVariable(T)>>> defined in brc.studybuddy.backend.wrapper.util in file PublisherExtensions.kt
  • public fun Mono<TypeVariable(T)>.toServiceResponse(): Mono<Response<TypeVariable(T)>> defined in brc.studybuddy.backend.wrapper.util in file PublisherExtensions.kt

请注意,第二个 toServiceResponse 可以根据第一个定义:

fun <T> Flux<T>.toServiceResponse(): Mono<Response<List<T>>> =
    this.collectList().toServiceResponse()

所以你几乎在 Monos 和 Fluxes 上做同样的事情,除了对于 Fluxes,你还先调用 collectList

val body = when (val value = result.returnValue) {
    is Mono<*> -> value
    is Flux<*> -> value.collectList()
    else -> throw RuntimeException("The \"body\" should be Mono<*> or Flux<*>!")
}.toServiceResponse()

或者,没有 when:

val body = result.returnValue.let { value ->
    (value as? Flux<*>)?.collectList() 
    ?: (value as? Mono<*>)
    ?: throw RuntimeException("The \"body\" should be Mono<*> or Flux<*>!")
}.toServiceResponse()