Hi. How can I pass a member function as an argumen...
# getting-started
b
Hi. How can I pass a member function as an argument to a function that accepts a interface? Here's my attempts:
Copy code
interface Consumer<T> {

    fun consume(item: T)
}

class SomeClass {

    fun processInteger(integer: Int) {

        println("I got ${integer}")
    }
}

fun invokeConsumerFunction(consumer: Consumer<Int>) {

    consumer.consume(123)
}

fun main(args: Array<String>) {

    val obj = SomeClass()

    // Attempts, neither of them compiles
    invokeConsumerFunction(obj.processInteger)
    invokeConsumerFunction({item -> obj.processInteger(item)})
}
Discovered one way to solve it, but it's a little bit verbose imo
Copy code
invokeConsumerFunction(object: Consumer<Int> {
        override fun consume(item: Int) {
            obj.processInteger(item)
        }
    })
Tried
Copy code
invokeConsumerFunction(obj::processInteger)
But it gives me the following error
Copy code
Error:(22, 28) Kotlin: Type mismatch: inferred type is KFunction1<@ParameterName Int, Unit> but Consumer<Int> was expected
p
give me a minute
b
Another attempt;
Copy code
interface Consumer<T> {

    fun consume(item: T)
}

class SomeClass {

    val intConsumer: Consumer<Int> = {integer -> processInteger(integer)}

    fun processInteger(integer: Int) {

        println("I got ${integer}")
    }
}

fun invokeConsumerFunction(consumer: Consumer<Int>) {

    consumer.consume(123)
}

fun main(args: Array<String>) {

    val obj = SomeClass()
    invokeConsumerFunction {obj.intConsumer}
}
Solved by @Pawel Urban
Copy code
typealias Consumer<T> = (T)->Unit

class SomeClass {

    fun processInteger(integer: Int) {
        println("I got ${integer}")
    }
}

fun invokeConsumerFunction(consumer: Consumer<Int>) {
    consumer(123)
}

fun main(args: Array<String>) {

    val obj = SomeClass()

    // this compiles just fine
    invokeConsumerFunction(obj::processInteger)
    invokeConsumerFunction({item -> obj.processInteger(item)})
}
a
@birgersp Is your
Consumer<T>
java or a kotlin interface?
b
@Andreas Sinz It's a Kotlin interface. I'm writing a Javascript application
a
kotlin supports SAM conversion for java interfaces, but not for kotlin interfaces right now https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
b
Aha, thanks. Now I'm trying this code:
Copy code
interface Consumer<T> {

    fun consume(item: T)
}

class SomeClass {

    val intConsumer = Consumer<Int> {integer -> {processInteger(integer)}} // <-- doesnt compile, "Interface Consumer does not have constructors"

    fun processInteger(integer: Int) {
        println("I got ${integer}")
    }
}

fun invokeConsumerFunction(consumer: Consumer<Int>) {
    consumer.consume(123)
}

fun main(args: Array<String>) {

    val obj = SomeClass()
    invokeConsumerFunction(obj.intConsumer)
}
But it doesnt work
a
@birgersp as I said, kotlin does not support SAM Conversion for kotlin interfaces yet. If you define your
Consumer<T>
with Java, your code should actually work
b
Okay. But since I'm creating a web-application (building to JS), I guess I cant be doing what you suggest?
a
@birgersp yes, but if you are working in a kotlin-only project, there is no need for having an interface with a single method, just use a Function-Type
(T) -> Unit
b
Awesome, thanks @Andreas Sinz!