skip to content

When should you reach for an object expression versus a lambda / SAM conversion when supplying an interface implementation in Kotlin?

level: seniorimportance: should knowfreq 40%

answer

  1. Single abstract method + Java/fun interface -> lambda (SAM)
  2. Multi-method / multi-supertype / class extension -> object expression
  3. Plain Kotlin interface needs fun interface for SAM
  4. Object expr allocates each eval; non-capturing lambda may be cached
  5. Extra state -> object expression

basics

~20 s

Use a lambda when the interface has a single method and you only need that one method. Use an object expression when you must implement several methods, keep state, or override members of a class.

solid answer

~40 s

If the target is a **functional (SAM) interface** — one abstract method — and you only need to supply that method, prefer a **lambda**: it's terser and, for Kotlin `fun interface`s or Java SAM types, the compiler does a **SAM conversion**. You can't use a plain lambda for a multi-method interface or to override members of an open/abstract **class**; there you need an **object expression**, which can implement several methods, add state and helper members, and call `super`. Object expressions also let you implement **multiple supertypes** at once. A subtle runtime difference: each evaluation of an object expression allocates a new instance; lambdas that capture nothing may be cached/optimized by the compiler. Choose lambdas for single-method callbacks; choose object expressions for richer, multi-member, or class-extending implementations.

code

kotlin · 11 lines
kotlin
fun interface Transformer { fun apply(x: Int): Int }

// SAM conversion: lambda allowed because of 'fun interface'
val doubler: Transformer = Transformer { it * 2 }

// Object expression needed: two methods
interface Lifecycle { fun start(); fun stop() }
val lc = object : Lifecycle {
    override fun start() = println("start")
    override fun stop() = println("stop")
}

go deeper

for a junior

Picks a lambda for simple single-method callbacks; may not know the fun interface nuance.

for a middle

Knows lambdas need a SAM/fun interface and that multi-method or class cases require an object expression.

for a senior

Articulates the fun interface requirement, multiple-supertype and class-extension cases, and the allocation/caching nuance.

for a principal

Weighs API ergonomics (defining fun interface for lambda-friendliness) against multi-method designs, and considers allocation in hot paths.

## The decision **Lambda / SAM conversion** fits when: - The target is a **functional interface**: one abstract method. This includes Java SAM types and Kotlin **`fun interface`** types. - You only need to provide that **one** method. ```kotlin val r = Runnable { println("hi") } // SAM conversion from a lambda val c = Comparator<Int> { a, b -> a - b } // SAM conversion (Java functional interface) ``` Note: Kotlin only performs SAM conversion for **Java** interfaces or interfaces declared **`fun interface`**. A regular Kotlin interface with one method does **not** auto-convert from a lambda unless marked `fun interface`. **Object expression** fits when you need any of: - To implement an interface with **more than one** abstract method. - To implement **multiple supertypes** at once. - To **extend a class** (open/abstract) and override its members, possibly calling `super`. - To carry **extra state or helper members** beyond the single method. ```kotlin val listener = object : MouseListener { // multi-method interface override fun onClick() {} override fun onHover() {} private var clicks = 0 // extra state } ``` ## Allocation / performance nuance - Each time an **object expression** is evaluated it **allocates a new instance**. - A **non-capturing lambda** may be compiled to a **singleton** (cached) instance; a capturing one allocates per capture. So in hot paths, a non-capturing lambda can be cheaper than an equivalent object expression. ## Readability - One method, no state -> lambda is clearer. - Several methods or state -> object expression keeps it organized and avoids forcing everything into one function. ## Quick rule > Single method, single interface, no extra state -> **lambda** (SAM). Otherwise -> **object expression**.

  • Why can't you pass a lambda to a single-method *Kotlin* interface by default?
    Kotlin only auto-converts lambdas for Java SAM types or interfaces marked `fun interface`; a plain Kotlin interface requires the `fun interface` modifier to enable SAM conversion.
  • Is there a performance difference between the two?
    An object expression allocates a new instance on each evaluation, while a non-capturing lambda may be optimized to a cached singleton, so lambdas can be cheaper in hot paths.

saying these in an interview costs you the question

  • Saying any single-method Kotlin interface accepts a lambda without `fun interface`
  • Claiming lambdas can override class members or multiple methods
  • Ignoring that object expressions allocate per evaluation
  • Asserting there is never any performance difference
  • Not recognizing multi-method interfaces require an object expression

context