- 9.1 Functions as Values
- 9.2 Currying
- 9.3 Function Literals
- 9.4 Functions Versus Methods
- 9.5 Single-Abstract-Method Interfaces
- 9.6 Partial Application
- 9.7 Closures
- 9.8 Inversion of Control
- 9.9 Summary
9.5 Single-Abstract-Method Interfaces
In hybrid languages, functions are objects, and lambda expressions are used as a convenient way to create such objects. Indeed, the lambda expression syntax is so handy that many languages let you use it to create instances of types other than functions.
A single-abstract-method (SAM) interface is an interface that contains exactly one abstract method. In Scala, for instance, the type Function[A,B] (or, equivalently, A => B) is a SAM interface with a single abstract method apply. We have used lambda expressions in code illustrations to create instances of Function[A,B], but it turns out that all SAM types can be instantiated using lambda expressions, even types that are not related to Function:
Scala
abstract class Formatter: def format(str: String): String def println(any: Any): Unit = Predef.println(format(any.toString))
Class Formatter defines only one abstract method format and is therefore a SAM interface. It can be implemented using lambda expressions:
Scala
val f: Formatter = str => str.toUpperCase f.println(someValue)
Note how method println is called on object f, which was defined as a lambda expression. This is possible only because f was declared with type Formatter; the expression (str => str.toUpperCase).println("foo") would make no sense.
Many Java interfaces can be implemented as lambdas, even though they predate Java’s syntax for lambda expressions and have little to do with functional programming:
Scala
val absComp: Comparator[Int] = (x, y) => x.abs.compareTo(y.abs) val stream: IntStream = ... val loggingStream: IntStream = stream.onClose(() => logger.info("closing stream"))
Comparator is a Java 2 SAM interface with an abstract method compare. Stream method onClose uses a single argument of type Runnable, a Java 1 SAM interface with an abstract method run. Both Comparator and Runnable can be implemented as lambda expressions.