ProgrammingKotlin Developer

What are the differences between regular classes, abstract classes, and interfaces in Kotlin, when and which tool to use?

Pass interviews with Hintsage AI assistant

Answer.

History of the question:

Kotlin combines the best of Java and the functional legacy of the JVM. Regular classes are declared as standard structures, abstract classes allow for the creation of under-defined templates with default implementation, and interfaces support multiple inheritance of behavior without state.

Problem:

The correct choice between a class, an abstract class, and an interface determines the architecture of the application, code granularity, and its extensibility. Incorrect inheritance leads to difficulties in testing and future changes.

Solution:

In Kotlin:

  • Regular class: defines structure and behavior. Can be inherited if declared open.
  • Abstract class: cannot be instantiated directly. May contain implementation and/or abstract (bodyless) methods.
  • Interface: implicitly open, implements contracts, allows method implementation but does not store state (only properties without backing field).

Code example:

interface Drawable { fun draw() } abstract class Shape(var color: String) : Drawable { abstract fun calcArea(): Double override fun draw() = println("Shape drawn") } class Circle(color: String, val radius: Double) : Shape(color) { override fun calcArea() = Math.PI * radius * radius }

Key features:

  • Interfaces allow multiple implementations, abstract classes allow only one
  • Interfaces cannot store state, abstract classes can
  • An abstract class can implement parts of interfaces and contain its own shared logic

Trick questions.

Can interfaces contain properties with backing field?

No, they can only define the property signature but cannot store data — properties without backing field.

Can you inherit from multiple classes?

No, Kotlin supports only single class inheritance but multiple interface implementations.

Can a constructor be declared in an interface?

No, an interface does not support constructors because it does not store state — only a behavior contract.

Typical mistakes and anti-patterns

  • Using abstract class instead of interface when not necessary
  • Storing state in interface (impossible, but mistakes are made during design)
  • Designing class hierarchies that complicate extension

Real-life example

Negative case

In the application, all common functions were moved to an abstract class, even if there was no internal logic or state, while the need was just for a common contract.

Pros:

  • One point of change for common logic

Cons:

  • Issues with multiple inheritance, difficult integration with other structures

Positive case

Only the necessary contracts were moved to interfaces, abstract classes were limited to common properties and methods requiring implementation.

Pros:

  • Flexible extension, modularity, clean contracts

Cons:

  • Requires early-stage design