简体   繁体   中英

Kotlin overload on lambdas that return a value VS ones that don't. Java, Groovy works, but Kotlin doesn't

very new to Kotlin and trying to make some of my API work in Kotlin without changing API much.

I have a method, let's call it client that receives a validation function. There are two variants of Validation . One that only suppose to do a validation, and the other can also return a value. To streamline user experience, in Java, I exposed two variants of the method. And it works as expected as I believe Java distincts between void and Object (<R>).

When I use my code in Kotlin, it can't distinct between two and I need to provide an explicit cast.

To remove Java from equation, I tried to replicate the situation in Kotlin using functional interfaces:

fun interface KotlinValidator {
    fun validate()
}

fun interface KotlinValidatorWithReturn {
    fun validateAndReturn(): Any
}

fun client(validator: KotlinValidator) {
    println("validator NO return")
    validator.validate()
}

fun client(validatorAndReturn: KotlinValidatorWithReturn): Any {
    println("validator WITH return")
    return validatorAndReturn.validateAndReturn()
}

fun test() {
    val fromValidator = client {
        100
    }

    val fromValidatorForced = client(KotlinValidatorWithReturn {
        100
    })

    client {
    }
}

it prints

validator NO return
validator WITH return
validator NO return

Based on my googling, it seems to be not possible to make it work without an explicit cast. However I hope that I am wrong as Groovy and Java let me do it.

To provide more context, I am trying to make WebTau HTTP module work nicely with Kotlin.

In Java and Groovy version I can do:

int id = http.post("/customers", customerPayload, ((header, body) -> {
    return body.get("id"); 
}));

http.put("/customers/" + id, changedCustomerPayload, ((header, body) -> {
    body.get("firstName").should(equal("FN"));
    body.get("lastName").should(equal(changedLastName));
}));

In Groovy:

def id = http.post("/customers", customerPayload) {
    body.id 
}

But in Kotlin:

val id: Int = http.post("/customers", customerPayload, HttpResponseValidatorWithReturn { _, body ->
    body.get("id")
})

The reason I brought this example is at the moment I am reluctant to change API and rename functions to distinct between the ones that return a value and the ones that don't.

The main problem is that in Kotlin, everything returns -- they may just return Unit . There is no void .

On the other hand, this may mean there is no need to distinguish between these types, you can just have the "with return" version.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM