ProgrammingAndroid Developer

Describe the differences between abstract classes and interfaces in Kotlin. When to apply which approach, what are the implementation features in the language and what are the nuances of inheritance?

Pass interviews with Hintsage AI assistant

Answer.

In Kotlin, abstract classes (abstract class) and interfaces (interface) are used to declare abstract logic, but there are significant differences between them:

  • An abstract class can contain state (fields), method implementations, and abstract methods. A class can inherit only one abstract (or regular) class. Constructors can be part of an abstract class.
  • An interface can declare properties (without state storage!), default method implementations, and abstract methods. Starting from Kotlin 1.1, an interface can contain property implementations, but they cannot have state. A class can implement multiple interfaces.
  • Interfaces cannot contain state (backing field), while abstract classes can.

Code Example

abstract class Animal(val name: String) { abstract fun makeSound() fun info() = println("I am $name") } interface Movable { fun move() } class Cat(name: String) : Animal(name), Movable { override fun makeSound() = println("Meow") override fun move() = println("Cat moves") }

Trick Question.

Can an interface in Kotlin contain state (backing field)?

Most people answer that properties can be declared in the interface, but they still do not have a backing field — only getters/setters without storing values. Even if you write get() = ... — the value will be computed each time.

Example:

interface MyInterface { val value: Int get() = 42 // no value storage, computed on the fly }

Examples of real mistakes due to ignorance of the topic nuances.


Story

In a large project, a senior developer tried to store state in an interface (e.g., a counter), expecting the property var count: Int to have a backing field. As a result, all implementing classes had to handle value storage differently, leading to unstable logic (data was lost if the setter was forgotten).


Story

One of the developers used an abstract class where multiple implementations of different behavior strategies were required (strategy pattern). This led to a problem: only one base class per hierarchy, but composition was needed for different aspects of behavior. The architecture had to be changed to interfaces.


Story

The team attempted to inherit from two abstract classes at once (one with logic, the other with common utilities), which is not possible in Kotlin. The problem emerged during the application expansion phase. This resulted in significant technical debt, as the classes had to be urgently reorganized.