Jan Vladimir Mostert
Jan Vladimir Mostert

Reputation: 12972

Pass function that receives params as param to class extension method

I'm trying to pass a function as parameter to a class extension method.

When doing

fun Router.handleJsonGet(path: String, method: () -> Any) {
    this.get(path).handler {
        it.response().putHeader("Content-Type", "application/json").end((gson.toJson(method())))
    }
}

I can easily wrap a function call inside a lambda and everything's working fine.

router.handleJsonGet("/business/list", { BusinessService.listBusinesses() })

Now I want to include a map of GET params and I'm getting stuck.

fun Router.handleJsonGet(path: String, method: (any:Any) -> Any) {
    this.get(path).handler {
        val map: MultiMap = it.request().params() ?: MultiMap.caseInsensitiveMultiMap()
        it.response().putHeader("Content-Type", "application/json").end((gson.toJson(method(map))))
    }
}

How do I make use of this method extension now? The wrap-with-lambda trick doesn't seem to work when the function requires a parameter.

I was expecting something like:

router.handleJsonGet("/business/list", BusinessService::listBusinesses)

with

object BusinessService {
    fun listBusinesses(any: Any) : List<Business> {
        // do something with any as MultiMap
        return Business.findAllBusinesss();
    } 
}

to work, but IntelliJ says Type Mismatch

Any idea how I should be passing a function that requires a parameter to a class extension method and how I should be calling it?

Upvotes: 2

Views: 820

Answers (2)

hotkey
hotkey

Reputation: 147901

The syntax you tried to use (BusinessService::listBusinesses) is not yet supported for objects in Kotlin 1.0.4, it is only planned for Kotlin 1.1 (Bound callable references).

Seems like you just need to use lambda with argument, either explicit or implicit it:

router.handleJsonGet("/business/list") { a -> BusinessService.listBusinesses(a) }

router.handleJsonGet("/business/list") { BusinessService.listBusinesses(it) }

Simplified example that demonstrates it:

object BusinessService {
    fun listBusinesses(any: Any): List<String> {
        return listOf("a", "b", "c");
    }
}

fun handleJsonGet(path: String, method: (Any) -> Any) {
    val map: Map<String, Int> = mapOf("a" to 1)
    method(map)
}

fun main(args: Array<String>) {
    handleJsonGet("1") { BusinessService.listBusinesses(it) }
}

Upvotes: 4

klimat
klimat

Reputation: 24991

Call it like this:

router.handleJsonGet("/business/list", {
   BusinessService.listBusinesses(anyParamHere)
})

Upvotes: 0

Related Questions