liveBook · Manning

Functional interface

As explained in Kotlin in Action, 2E

A functional interface is an interface with exactly one abstract method, allowing it to be implemented by a function value or lambda in compatible contexts.

A functional interface, also called a single abstract method (SAM) interface, has exactly one abstract method. Kotlin can convert a lambda into an implementation when a Java API expects such an interface, replacing the anonymous-object boilerplate formerly common in Java. This keeps callback-style JVM code concise while preserving the interface expected by the API. section 5.2 section 5.5

Pass a lambda to a Java listener

Given a Java listener whose single abstract method is `onClick(View)`, Kotlin maps the lambda parameter to that method parameter: `button.setOnClickListener { view -> /* handle click */ }` The lambda is converted to an `OnClickListener` implementation. The same pattern works for Java APIs accepting `Runnable`, `Callable`, and other functional interfaces. section 5.2 section 5.2.1

SAM conversion is automatic at many Java method call sites. A lambda passed to a `Runnable` parameter supplies the body of `run`. For Java functional-interface calls, a noncapturing lambda can reuse its generated instance; a lambda that captures surrounding values requires a new object that stores those values. This implementation detail does not describe Kotlin `inline` function calls, where anonymous classes need not be created. section 5.2.1

Use a SAM constructor when a lambda must become an interface value outside an automatically converted call site. The constructor has the interface name: `Runnable { println("All done!") }`. It can return a SAM value or store one listener for reuse. Choose an anonymous object instead when a listener must refer to itself with `this`, such as to unregister itself during event handling. section 5.2.2

Listing 5.14 A functional interface in Kotlin contains exactly one abstract method
fun interface IntCondition {
    fun check(i: Int): Boolean                        #1
    fun checkString(s: String) = check(s.toInt())     #2
    fun checkChar(c: Char) = check(c.digitToInt())    #2
}
 
fun main() {
    val isOdd = IntCondition { it % 2 != 0 }
    println(isOdd.check(1))
    // true
    println(isOdd.checkString("2"))
    // false
    println(isOdd.checkChar('3'))
    // true
}

A Kotlin `fun interface` declares one abstract operation while retaining useful concrete helper methods. `IntCondition` supplies `check` through a lambda and delegates string and character helpers to it. section 5.3

Kotlin can define its own SAM types with `fun interface`. Such a type has one abstract method but may add non-abstract methods, making it useful when a plain function type lacks needed behavior or a clearer named contract is desirable. Functions accepting a `fun interface` can receive a lambda directly or a compatible function reference. For APIs intended for Java callers, a `fun interface` also avoids the `Unit`-returning function-type call pattern. section 5.3

How Kotlin in Action, 2E covers it

How deep it goes
Explains automatic and explicit SAM conversion, allocation effects of captures, and self-unregistering listener limits.
Examples
Uses button click listeners, Runnable postponement, reusable listeners, and an IntCondition predicate with helper methods.
What it assumes
Assumes familiarity with lambdas while contrasting them with Java anonymous classes and introducing Kotlin fun interfaces.
What you can do after
Apply it via Kotlin lambdas and SAM constructors when calling or defining Java- and Kotlin-facing callback APIs.
How it connects
Connects lambdas, anonymous objects, function types, function references, inline functions, and Java interoperability.

Also explained in

Compare how 3 books explain functional interface →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Kotlin in Action, 2E. The section links point to the parts of the book it draws on.