# Interfaces

An interface describes the concept of a type. It is a prototype for all classes that implement the interface.

It describes what a class should do, but not how it should do it. An interface provides a form, but generally no implementation. It specifies an object’s actions without detailing how those actions are performed. The interface describes the mission or goal of an entity, versus a class that contains implementation details.

One dictionary definition says that an interface is “The place at which independent and often unrelated systems meet and act on or communicate with each other.” Thus, an interface is a means of communication between different parts of a system.

An Application Programming Interface (API) is a set of clearly defined communication paths between various software components. In object-oriented programming, the API of an object is the set of public members it uses to interact with other objects.

Code using a particular interface only knows what functions can be called for that interface. The interface establishes a “protocol” between classes. (Some object-oriented languages have a keyword called protocol to do the same thing.)

To create an interface, use the interface keyword instead of the class keyword. When defining a class that implements an interface, follow the class name with a : (colon) and the name of the interface:

// Interfaces/Computer.kt
package interfaces
import atomictest.*

interface Computer {
  fun prompt(): String
  fun calculateAnswer(): Int

class Desktop : Computer {
  override fun prompt() = "Hello!"
  override fun calculateAnswer() = 11

class DeepThought : Computer {
  override fun prompt() = "Thinking..."
  override fun calculateAnswer() = 42

class Quantum : Computer {
  override fun prompt() = "Probably..."
  override fun calculateAnswer() = -1

fun main() {
  val computers = listOf(
    Desktop(), DeepThought(), Quantum()
  computers.map { it.calculateAnswer() } eq
    "[11, 42, -1]"
  computers.map { it.prompt() } eq
    "[Hello!, Thinking..., Probably...]"

Computer declares prompt() and calculateAnswer() but provides no implementations. A class that implements the interface must provide bodies for all the declared functions, making those functions concrete. In main() you see that different implementations of an interface express different behaviors via their function definitions.

When implementing a member of an interface, you must use the override modifier. override tells Kotlin you are intentionally using the same name that appears in the interface (or base class)—that is, you aren’t accidentally overriding.

An interface can declare properties. These must be overridden in all classes implementing that interface:

// Interfaces/PlayerInterface.kt
package interfaces
import atomictest.eq

interface Player {
  val symbol: Char

class Food : Player {
  override val symbol = '.'

class Robot : Player {
  override val symbol get() = 'R'

class Wall(override val symbol: Char) : Player

fun main() {
  listOf(Food(), Robot(), Wall('|')).map {
  } eq "[., R, |]"

Each subclass overrides the symbol property in a different way:

  • Food directly replaces the symbol value.
  • Robot has a custom getter that returns the value (see [Property Accessors](javascript:void(0))).
  • Wall overrides symbol inside the constructor argument list (see [Constructors](javascript:void(0)))

An enumeration can implement an interface:

// Interfaces/Hotness.kt
package interfaces
import atomictest.*

interface Hotness {
  fun feedback(): String

enum class SpiceLevel : Hotness {
  Mild {
    override fun feedback() =
      "It adds flavor!"
  Medium {
    override fun feedback() =
      "Is it warm in here?"
  Hot {
    override fun feedback() =
      "I'm suddenly sweating a lot."
  Flaming {
    override fun feedback() =
      "I'm in pain. I am suffering."

fun main() {
  SpiceLevel.values().map { it.feedback() } eq
    "[It adds flavor!, " +
    "Is it warm in here?, " +
    "I'm suddenly sweating a lot., " +
    "I'm in pain. I am suffering.]"

The compiler ensures that each enum element provides a definition for feedback().

# SAM Conversions

The Single Abstract Method (SAM) interface comes from Java, where they call member functions “methods.” Kotlin has a special syntax for defining SAM interfaces: fun interface. Here we show SAM interfaces with different parameter lists:

// Interfaces/SAM.kt
package interfaces

fun interface ZeroArg {
  fun f(): Int

fun interface OneArg {
  fun g(n: Int): Int

fun interface TwoArg {
  fun h(i: Int, j: Int): Int

When you say fun interface, the compiler ensures there is only a single member function.

You can implement a SAM interface in the ordinary verbose way, or by passing it a lambda; the latter is called a SAM conversion. In a SAM conversion, the lambda becomes the implementation for the single method in the interface. Here we show both ways to implement the three interfaces:

// Interfaces/SAMImplementation.kt
package interfaces
import atomictest.eq

class VerboseZero : ZeroArg {
  override fun f() = 11

val verboseZero = VerboseZero()

val samZero = ZeroArg { 11 }

class VerboseOne : OneArg {
  override fun g(n: Int) = n + 47

val verboseOne = VerboseOne()

val samOne = OneArg { it + 47 }

class VerboseTwo : TwoArg {
  override fun h(i: Int, j: Int) = i + j

val verboseTwo = VerboseTwo()

val samTwo =  TwoArg { i, j -> i + j }

fun main() {
  verboseZero.f() eq 11
  samZero.f() eq 11
  verboseOne.g(92) eq 139
  samOne.g(92) eq 139
  verboseTwo.h(11, 47) eq 58
  samTwo.h(11, 47) eq 58

Comparing the “verbose” implementations to the “sam” implementations you can see that SAM conversions produce much more succinct syntax for a commonly-used idiom, and you aren’t forced to define a class to create a single object.

You can pass a lambda where a SAM interface is expected, without first wrapping it into an object:

// Interfaces/SAMConversion.kt
package interfaces
import atomictest.trace

fun interface Action {
  fun act()

fun delayAction(action: Action) {

fun main() {
  delayAction { trace("Hey!") }
  trace eq "Delaying... Hey!"

In main() we pass a lambda instead of an object that implements the Action interface. Kotlin automatically creates an Action object from this lambda.

Exercises and solutions can be found at www.AtomicKotlin.com.