Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I create a lambda expression from a Kotlin interface?

Tags:

kotlin

I have a simple Kotlin interface:

@FunctionalInterface
interface ServiceMethod<T> {
  fun doService(): T
}

This, in spite of the name, is essentially identical to Java's Supplier functional interface. The only difference is that I can implement the Supplier, and I can't implement my own.

val supplier = Supplier<String> {
  "Hello"
}
val serviceMethod = ServiceMethod<String> {
  "Hello"
}

The ServiceMethod implementation gives me a compiler error saying "Interface ServiceMethod does not have constructors." Huh? Of course it doesn't! It's a functional interface.

I know that I can write it as an anonymous inner class:

val serviceMethod = object : ServiceMethod<String> {
  override fun doService(): String {
    return "Hello"
  }
}

But this is much more verbose. In this case I could just use the Supplier interface, but that won't work for other interfaces. I shouldn't have to write an interface in Java, just to be able to a lambda in Kotlin. I'd rather use a lambda for all my Kotlin interfaces, especially since I'll be writing a lot of these. Am I missing something obvious?

like image 531
MiguelMunoz Avatar asked Aug 31 '20 08:08

MiguelMunoz


People also ask

How do you make a lambda expression in Kotlin?

A lambda expression is always surrounded by curly braces, argument declarations go inside curly braces and have optional type annotations, the code_body goes after an arrow -> sign. If the inferred return type of the lambda is not Unit, then the last expression inside the lambda body is treated as return value.

Can we use lambda expression in interface?

The Lambda expression is used to provide the implementation of an interface which has functional interface. It saves a lot of code. In case of lambda expression, we don't need to define the method again for providing the implementation.

Does Kotlin support lambda expressions?

You use lambda expressions extensively in Android development and more generally in Kotlin programming.

How do I create an instance of an interface in Kotlin?

In Kotlin, we can create an object expression of an interface by implementing its abstract methods. This implementation technique is known as anonymous interface.


1 Answers

Use the fun interface modifier since Kotlin 1.4

In Kotlin 1.3 and earlier, SAM (single abstract method) conversions, where you can instantiate an interface like Supplier using a lambda function, were only supported for Java interfaces.

The language designers originally thought SAM conversions wouldn't be useful for Kotlin interfaces, because a Kotlin function already has a type. For example, the type of your doService function can be written as () -> T. Instead of creating an object that implements an interface, you could simply write:

val serviceMethod: () -> String = { "Hello" }

Kotlin 1.4 adds SAM conversions for Kotlin interfaces, but it doesn't work out of the box for every interface. Instead, you have to apply the special fun modifier to a Kotlin interface to make it eligible for SAM conversion.

In your example, it would simply look like this:

fun interface ServiceMethod<T> {
  fun doService(): T
}

With the modifier added, you can create an instance using a lambda exactly as you were hoping in your question.

val serviceMethod = ServiceMethod<String> { "Hello" }

You can learn more in the Kotlin documentation for functional interfaces.

like image 134
Sam Avatar answered Sep 21 '22 06:09

Sam