How do I use abstract classes and methods in Kotlin?

In Kotlin, an abstract class is a class that cannot be instantiated directly. It is meant to be subclassed.

An abstract method is a method declared without an implementation. Subclasses must override it.

Basic example

abstract class Animal {
    abstract fun makeSound()

    fun sleep() {
        println("Sleeping...")
    }
}

class Dog : Animal() {
    override fun makeSound() {
        println("Woof!")
    }
}

fun main() {
    val dog = Dog()
    dog.makeSound()
    dog.sleep()
}

Output:

Woof!
Sleeping...

Key points

1. Use abstract before the class

abstract class Shape

You cannot create an instance of it:

val shape = Shape() // Error

2. Abstract methods have no body

abstract fun area(): Double

A subclass must implement them:

class Circle(val radius: Double) : Shape() {
    override fun area(): Double {
        return Math.PI * radius * radius
    }
}

3. Abstract classes can have regular methods

abstract class Shape {
    abstract fun area(): Double

    fun describe() {
        println("This is a shape")
    }
}

4. Abstract properties are allowed

abstract class Vehicle {
    abstract val maxSpeed: Int
}

class Car : Vehicle() {
    override val maxSpeed: Int = 200
}

5. Abstract classes can have constructors

abstract class Person(val name: String) {
    abstract fun work()
}

class Developer(name: String) : Person(name) {
    override fun work() {
        println("$name writes code")
    }
}

Complete example

abstract class Shape(val name: String) {
    abstract fun area(): Double

    fun printInfo() {
        println("$name has area ${area()}")
    }
}

class Rectangle(
    name: String,
    val width: Double,
    val height: Double
) : Shape(name) {
    override fun area(): Double {
        return width * height
    }
}

class Circle(
    name: String,
    val radius: Double
) : Shape(name) {
    override fun area(): Double {
        return Math.PI * radius * radius
    }
}

fun main() {
    val shapes = listOf(
        Rectangle("Rectangle", 5.0, 3.0),
        Circle("Circle", 2.0)
    )

    for (shape in shapes) {
        shape.printInfo()
    }
}

Abstract class vs interface

Use an abstract class when you want to share state or constructor logic:

abstract class BaseRepository(val tableName: String) {
    abstract fun findAll(): List<String>
}

Use an interface when you mainly want to define behavior:

interface Drawable {
    fun draw()
}

A class can extend only one abstract class, but it can implement multiple interfaces:

abstract class Animal

interface Runnable {
    fun run()
}

interface Swimmable {
    fun swim()
}

class Duck : Animal(), Runnable, Swimmable {
    override fun run() {
        println("Duck runs")
    }

    override fun swim() {
        println("Duck swims")
    }
}

In short: use abstract class for a shared base with common implementation/state, and use abstract fun or abstract val for members subclasses must provide.

How do I create and implement abstract class?

Abstract class is a class that have one or more methods declared, but not defined. Abstract class cannot have instances. This class uses in inheritance to take advantage of polymorphism. To declare that a class is abstract, use the abstract keyword in front of the class keyword in the class definition.

Methods in abstract class that have no definition are called abstract methods. The declaration for an abstract method ends with a semicolon and you specify the method with the abstract keyword to identify it as such. The implementation is left to the sub classes.

package org.kodejava.example.fundamental;

public abstract class Animal {
    private String species;

    public Animal(String species) {
        this.species = species;
    }

    public abstract void makeASound();

    public String getSpecies() {
        return species;
    }

    public static void main(String[] args) {
        Animal pig = new Pig("Warthog");
        pig.makeASound();
    }
}

The Pig class extends the Animal class. Because the Animal class contains an abstract method makeASound() the Pig class must implements this method or else the Pig will also become an abstract class.

package org.kodejava.example.fundamental;

public class Pig extends Animal {

    public Pig(String species) {
        super(species);
    }

    @Override
    public void makeASound() {
        System.out.println("oink oink");
    }
}