7

I'm learning Kotlin and I have some trouble with functions. I'm trying to create something like a functional interface with a generic parameter. In Java I would create something like this:

@FunctionalInterface
public interface Foo<T extends Bar> {
    String something(T arg);
}

Then I can use this somewhere else like this (given that Person extends Bar:


Foo<Person> f = p -> p.toString();

How do you write this with Kotlin?

The first thing I tried was to use type-aliases like this:

typealias Foo<T> = (T) -> String

However, it stopped working when I added the bound to the type parameter:

typealias Foo<T: Bar> = (T) -> String  // Error: Bounds are not allowed on type alias parameters

The second approach was to write an interface that extends the function type:

interface Foo<T: Bar> : (T) -> String

However, now I don't know how to instantiate a lambda function from with this. It works when I create class from it like this:

class Something: Foo<Person> {
    override fun invoke(p: Person): String {
        return p.toString()
    }
}

val f = Something()

But this is a big overhead and I'm sure there has to be a better solution.

So how can I define a function signature that can be reused by many functions that supports generic parameters with bounds in kotlin?

1

1 Answer 1

6

Most of the time (always?) it is sufficient to define the type of the lambda in the parameter of the function that receives it.

For example:

open class Bar
class Person: Bar()

var f = { p: Person -> p.toString() }

fun <T : Bar> withFoo(block: (T) -> String) { }
fun <T : Bar> otherFoo(block: (T) -> String) { }   

fun main() {
    withFoo(f)
    otherFoo(f)
}

The same way the Kotlin documentation states: "since Kotlin has proper function types, automatic conversion of functions into implementations of Kotlin interfaces is unnecessary and therefore unsupported."

See https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.