Question

Kotlin Interfaces and SAM Conversion: Why "Interface Does Not Have Constructors" Happens

kotlinjava

Question

I am converting Java code to Kotlin and I am confused about how to create an instance of an interface.

In Java, I have this interface:

public interface MyInterface {
    void onLocationMeasured(Location location);
}

In Kotlin, I can create an instance of that Java interface like this:

val myObj = MyInterface {
    Log.d("...", "...")
}

This works.

But after converting the interface itself to Kotlin:

interface MyInterface {
    fun onLocationMeasured(location: Location)
}

I now get the error:

Interface MyInterface does not have constructors

when I try to instantiate it in the same style.

It seems like only the syntax changed. Why does this happen in Kotlin, and what is the correct way to create an instance of a Kotlin-defined interface?

Short Answer

By the end of this page, you will understand why Kotlin lets you create Java single-method interfaces with lambda syntax, why the same syntax does not automatically work for Kotlin-defined interfaces, and how to correctly instantiate Kotlin interfaces using object expressions or fun interface when appropriate.

Concept

The core concept behind this question is SAM conversion.

SAM stands for Single Abstract Method. A SAM type is an interface that has exactly one abstract method. In Java, interfaces like this are often used as callbacks:

public interface MyInterface {
    void onLocationMeasured(Location location);
}

Because there is only one method to implement, Kotlin can often let you replace the full anonymous class with a lambda.

Why the Java version works

When MyInterface is defined in Java and has one abstract method, Kotlin recognizes it as a Java SAM interface. That means this is allowed:

val myObj = MyInterface {
    Log.d("TAG", "measured")
}

Kotlin converts the lambda into an object that implements the interface.

Why the Kotlin version fails

When you rewrite the interface in Kotlin as:

interface MyInterface {
    fun onLocationMeasured(location: Location)
}

it is now just a normal Kotlin interface. A normal interface is not a class and does not have a constructor. So Kotlin does not treat MyInterface { ... } as "call a constructor" or "build an implementation" unless the interface is specifically declared as a functional interface.

That is why the compiler says:

Interface MyInterface does not have constructors

The important rule

In Kotlin, there are two common ways to create an implementation of an interface:

  • Use an object expression for a normal interface
  • Use a lambda only for a SAM-compatible interface

For Kotlin-defined interfaces, lambda instantiation works only when the interface is declared with:

fun interface MyInterface {
    fun onLocationMeasured(location: Location)
}

A fun interface is Kotlin's way of saying: this interface is a functional interface with one abstract method, so it can be created from a lambda.

Why this matters

This concept shows up often in real code:

  • click listeners
  • network callbacks
  • event handlers
  • background task completion handlers
  • stream or collection processing

Understanding when to use an object expression versus a lambda helps you read Kotlin APIs correctly and design your own APIs in a more idiomatic way.

Mental Model

Think of a normal Kotlin interface as a contract sheet.

It says:

  • "Any class using me must provide these methods"

But it does not come with a built-in factory or constructor.

So this does not make sense:

MyInterface { ... }

because you are writing something that looks like calling a constructor, but an interface is not constructible.

Now think of a fun interface as a special one-button adapter.

Because it has only one job, Kotlin can say:

  • "If you give me a lambda, I know how to turn that into an implementation."

So:

val myObj = MyInterface { location ->
    println(location)
}

works only when Kotlin knows the interface is a functional interface.

Simple analogy

  • interface = a job description
  • object : Interface { ... } = hiring a worker and explicitly telling them how to do the job
  • fun interface + lambda = using a quick one-task freelancer form because there is only one task to define
Take Quiz

Syntax and Examples

1. Normal Kotlin interface: use an object expression

interface MyInterface {
    fun onLocationMeasured(location: Location)
}

val myObj = object : MyInterface {
    override fun onLocationMeasured(location: Location) {
        Log.d("TAG", "Location measured: $location")
    }
}

This is the correct way to create an instance of a regular Kotlin interface.

Why it works

  • object : MyInterface creates an anonymous object
  • That object implements MyInterface
  • You must override all required abstract methods

2. Kotlin functional interface: use fun interface

fun interface MyInterface {
    fun onLocationMeasured(location: Location)
}

val myObj = MyInterface { location ->
    Log.d("TAG", "Location measured: $location")
}

This works because fun interface tells Kotlin the interface supports SAM conversion.

3. Java interface used from Kotlin

public interface MyInterface {
    void onLocationMeasured(Location location);
}
val myObj = MyInterface { location ->
    Log.d("TAG", "Location measured: $location")
}

Kotlin supports SAM conversion for Java functional interfaces.

4. If you need more than one method, use a normal interface

interface TrackerListener {
    fun onStart()
    fun onLocationMeasured(location: Location)
}

val listener = object : TrackerListener {
    override fun onStart() {
        Log.d("TAG", "Tracking started")
    }

    override fun onLocationMeasured(location: Location) {
        Log.d("TAG", "Measured: $location")
    }
}

A lambda cannot represent multiple abstract methods, so you must use an object expression here.

Step by Step Execution

Consider this Kotlin code:

fun interface MyInterface {
    fun onLocationMeasured(location: String)
}

fun main() {
    val myObj = MyInterface { location ->
        println("Measured: $location")
    }

    myObj.onLocationMeasured("Paris")
}

Step by step

1. Kotlin sees fun interface

fun interface MyInterface {

This tells the compiler:

  • this interface has one abstract method
  • it can be instantiated from a lambda

2. Kotlin reads the lambda assignment

val myObj = MyInterface { location ->
    println("Measured: $location")
}

Kotlin converts this lambda into an object that implements MyInterface.

Conceptually, it is similar to:

val myObj = object : MyInterface {
    override fun onLocationMeasured(location: String) {
        println("Measured: $location")
    }
}

3. The method is called

myObj.onLocationMeasured("Paris")

This invokes the single abstract method of the generated implementation.

4. Output appears

Measured: Paris

What happens in the failing version

If you change fun interface to just interface:

interface MyInterface {
    fun onLocationMeasured(location: String)
}

then this line:

val myObj = MyInterface { location ->
    println(location)
}

is no longer valid, because Kotlin tries to interpret MyInterface(...) like a constructor-style call. But interfaces do not have constructors.

Real World Use Cases

Callback APIs

Interfaces are commonly used to receive events from another part of the program.

Examples:

  • location updates
  • button click handlers
  • download completion events
  • sensor readings
fun interface OnDownloadComplete {
    fun onDone(fileName: String)
}

Android listeners

In Android, many Java-based APIs use listener interfaces. Kotlin often lets you pass lambdas for these because they are Java SAM interfaces.

button.setOnClickListener {
    Log.d("TAG", "Clicked")
}

Custom Kotlin APIs

If you are designing your own callback API in Kotlin and want callers to use lambdas, fun interface is often a good choice.

fun interface OnUserLoaded {
    fun onLoaded(name: String)
}

Multiple related callbacks

If your API needs several methods, a regular interface is more appropriate.

interface UploadListener {
    fun onStart()
    fun onProgress(percent: Int)
    fun onComplete()
}

Then users implement it with an object expression or a named class.

Take Quiz

Real Codebase Usage

In real projects, developers choose between lambdas and object expressions based on API design.

Pattern 1: Simple callback with fun interface

Use this when there is only one action to perform.

fun interface OnSave {
    fun onSave(fileName: String)
}

This keeps call sites clean:

saveDocument(OnSave { fileName ->
    println("Saved $fileName")
})

Pattern 2: Object expression for richer behavior

If the interface has multiple methods or stateful logic, use an object expression.

interface AuthListener {
    fun onSuccess(userId: String)
    fun onError(message: String)
}

val listener = object : AuthListener {
    override fun onSuccess(userId: String) {
        println("User: $userId")
    }

    override fun onError(message: String) {
        println("Error: $message")
    }
}

Pattern 3: Guard clauses inside callbacks

Callbacks often validate input early.

fun interface OnLocationMeasured {
    fun onLocationMeasured(location: String)
}

val handler = OnLocationMeasured { location ->
    if (location.isBlank()) return@OnLocationMeasured
    println(location)
}

Pattern 4: Error handling in event code

val handler = OnLocationMeasured { location ->
    try {
        println("Processing $location")
    } catch (e: Exception) {
        println("Failed: ${e.message}")
    }
}

Pattern 5: Configuration and dependency passing

A callback interface is often stored and called later.

class LocationTracker(private val listener: OnLocationMeasured) {
    fun simulate() {
        listener.onLocationMeasured("Berlin")
    }
}

Common Mistakes

1. Treating a normal interface like a constructor

Broken code:

interface MyInterface {
    fun onLocationMeasured(location: String)
}

val obj = MyInterface {
    println(it)
}

Why it fails:

  • MyInterface is not a class
  • it has no constructor
  • normal Kotlin interfaces do not support lambda instantiation

Fix:

val obj = object : MyInterface {
    override fun onLocationMeasured(location: String) {
        println(location)
    }
}

2. Forgetting to use fun interface

Broken code:

interface OnDone {
    fun complete()
}

val callback = OnDone {
    println("done")
}

Fix:

fun interface OnDone {
    fun complete()
}

3. Using fun interface when there is more than one abstract method

Broken code:

fun interface BadExample {
    fun start()
    fun stop()
}

Why it fails:

  • a functional interface must have exactly one abstract method

Fix:

interface GoodExample {
    fun start()
    fun stop()
}

and instantiate with an object expression.

4. Forgetting override in an object expression

Broken code:

val obj = object : MyInterface {
    fun onLocationMeasured(location: String) {
        println(location)
    }
}

Fix:

val obj = object : MyInterface {
    override fun onLocationMeasured(location: String) {
        println(location)
    }
}

5. Assuming Java and Kotlin interfaces behave identically in all cases

They are similar, but Kotlin has specific rules for SAM conversion. A Java single-method interface may accept a lambda even if a regular Kotlin interface with the same shape does not.

Comparisons

ConceptKotlin syntaxLambda allowed?Best use case
Java single-method interfaceinterface in JavaYes, from KotlinExisting Java callback APIs
Kotlin normal interfaceinterface MyInterfaceNoMultiple methods or richer contracts
Kotlin functional interfacefun interface MyInterfaceYesKotlin callback APIs with one abstract method
Anonymous objectobject : MyInterface { ... }Not a lambda, but always works for interfacesCustom one-off implementations

interface vs fun interface

Featureinterfacefun interface
Number of abstract methodsOne or moreExactly one
Can be instantiated with lambdaNoYes
Good for callbacksSometimesYes
Good for complex contractsYesUsually no

Object expression vs lambda

ApproachExampleWhen to use
Object expressionobject : MyInterface { ... }Need full explicit implementation
LambdaMyInterface { ... }Interface is SAM-compatible

The key difference is that a lambda is only shorthand for a single-method functional interface.

Take Quiz

Cheat Sheet

Quick rules

  • A normal Kotlin interface has no constructor.
  • MyInterface { ... } only works for SAM-compatible interfaces.
  • Java single-method interfaces are usually SAM-compatible in Kotlin.
  • Kotlin-defined interfaces need fun interface for lambda instantiation.
  • If the interface has multiple abstract methods, use object : InterfaceName { ... }.

Normal interface

interface MyInterface {
    fun onLocationMeasured(location: String)
}

val obj = object : MyInterface {
    override fun onLocationMeasured(location: String) {
        println(location)
    }
}

Functional interface

fun interface MyInterface {
    fun onLocationMeasured(location: String)
}

val obj = MyInterface { location ->
    println(location)
}

Remember

  • interface = contract
  • fun interface = contract that can be backed by a lambda
  • object : Interface = anonymous implementation

Common compiler clue

If you see:

Interface ... does not have constructors

check whether:

  • you tried to instantiate a normal interface like a constructor
  • you actually needed an object expression
  • the interface should be a fun interface

FAQ

Why does Kotlin say an interface does not have constructors?

Because an interface is not a class you can instantiate directly. MyInterface { ... } only works when Kotlin supports SAM conversion for that interface.

Why did the Java interface work but the Kotlin one did not?

Kotlin supports SAM conversion for Java single-method interfaces. A regular Kotlin interface does not automatically get the same treatment.

How do I instantiate a Kotlin interface correctly?

Use an object expression:

val obj = object : MyInterface {
    override fun onLocationMeasured(location: Location) {
        // code
    }
}

When should I use fun interface?

Use it when your Kotlin interface has exactly one abstract method and you want callers to be able to pass a lambda.

Can a fun interface have more than one method?

It can only have one abstract method. Additional non-abstract members may be allowed, but the functional part must remain exactly one abstract method.

Is a lambda the same as an object expression?

Not exactly. A lambda is shorthand for implementing a functional interface or function type. An object expression creates an anonymous object explicitly.

Should I use a function type instead of a fun interface?

Sometimes yes. If you only need a simple callback, a function type like (Location) -> Unit can be even simpler. Use fun interface when you want a named contract.

Take Quiz

Mini Project

Description

Build a small location event handler that demonstrates both ways of implementing interface-based callbacks in Kotlin: using an object expression for a normal interface and using a lambda for a fun interface. This mirrors real app code where one component reports events and another reacts to them.

Goal

Create a simple program that sends location updates to listeners using both a regular Kotlin interface and a functional Kotlin interface.

Requirements

  • Define one regular Kotlin interface with a single method.
  • Define one fun interface with a single method.
  • Create an implementation of the regular interface using an object expression.
  • Create an implementation of the functional interface using a lambda.
  • Call both listeners and print their output.
Take Quiz

Keep learning

Related questions

View more