Start learning free

LESSON 189 OF 348 · OBJECT-ORIENTED PROGRAMMING

Abstract Classes in Kotlin: Abstract Members and Override

Lesson Read the full explanation

TL ; DR:

An abstract class is a class you can't instantiate directly — it's a half-finished template. It can declare methods with no body (abstract methods) that any concrete subclass must implement.


abstract class Animal {
    abstract fun speak()   // no body — concrete
                           // subclasses must provide one
}
class Dog : Animal() {
    override fun speak() {
        println("Woof")
    }
}


Full lesson:

Sometimes you want to capture shared behavior across a family of classes without committing to one concrete implementation. For example, every Animal can speak(), but exactly how depends on whether it's a Dog or a Cat. That's what abstract classes are for.

Two superpowers

  1. You can't write new Animal() directly — the compiler/runtime stops you. You have to pick a concrete subclass.
  2. Any subclass MUST implement every abstract method, or the compiler/runtime complains. The abstract class is a contract with teeth.

Mixing abstract and concrete

An abstract class can also have concrete methods (with bodies) and fields. Those are shared by all subclasses for free, just like normal inheritance. Only the methods marked abstract require an override.

Notes by language

  • C# / Java — keyword abstract on the class and on the method.
  • Python — inherit from abc.ABC and decorate the method with @abstractmethod.
  • JavaScript — no built-in support. The convention is a parent class whose method throws an error if not overridden.
  • C++ — a method ending with = 0 is "pure virtual"; a class with any pure virtual method is abstract.

Your task

The abstract Animal class is already defined. Create a concrete Dog subclass and implement the speak method so it prints "Woof". The harness builds a Dog and calls speak().

Expected output:

Woof
STEP 1 OF 2
    Ctrl + Enter to check

    KOTLIN · OBJECT-ORIENTED PROGRAMMING

    Abstract Classes in Kotlin, explained

    What an abstract class is

    An abstract class is a class that is meant to be extended, never created directly. It describes what every member of a family of classes has in common and leaves some pieces open for the subclasses to fill in. Those open pieces are abstract members: they are declared with a signature but no body.

    In Kotlin you mark both the class and the open member with the abstract keyword:

    abstract class Animal {
        abstract fun speak()
    }
    

    Every animal can speak, but how it speaks depends on the kind of animal. Animal states the promise (speak() exists) and each concrete subclass decides what it does. The abstract class acts as a contract that the compiler enforces.

    The two rules the compiler enforces

    You can't create an instance of an abstract class

    Kotlin has no new keyword. Calling the class name, as in Animal(), creates an object, and for an abstract class the compiler refuses:

    abstract class Animal { abstract fun speak() }
    
    fun main() {
        val x = Animal()
    }
    

    The error is cannot create an instance of an abstract class. To get an object you need a concrete subclass.

    A concrete subclass must implement every abstract member

    A class that extends Animal and does not provide speak() is itself incomplete. The compiler reports class 'Cat' is not abstract and does not implement abstract base class member, followed by the missing function. The only way around it is to make the subclass abstract too and leave the work to its own subclasses.

    Step by step: the exercise

    The lesson gives you the abstract Animal class and a Solution class whose mainFunction creates a Dog and calls speak() on it. The program must print Woof, so the missing piece is the Dog class.

    1. Declare Dog as a subclass of Animal. Write class Dog : Animal(). The colon means "extends". The parentheses after Animal are the call to the parent's constructor, and Kotlin requires them whenever the parent is a class. Without them the compiler says this type has a constructor, so it must be initialized here.
    2. Override speak. Inside Dog, write override fun speak() with a body that calls println("Woof"). The override keyword is mandatory in Kotlin. It tells the compiler, and the reader, that this function fills in a member declared by a parent.

    With both steps done, mainFunction compiles. Its call rex.speak() runs the version inside Dog and prints Woof.

    The solution in Kotlin

    abstract class Animal {
        abstract fun speak()
    }
    
    class Dog : Animal() {
        override fun speak() {
            println("Woof")
        }
    }
    
    class Solution {
        fun mainFunction() {
            val rex = Dog()
            rex.speak()
        }
    }
    

    The Kotlin details worth knowing:

    • Abstract members are open automatically. Classes and members are final by default in Kotlin, so a normal function can't be overridden unless it is marked open. An abstract member exists only to be overridden, so you never write open next to abstract.
    • override is required. Writing fun speak() in Dog without it is a compile error: 'speak' hides member of supertype 'Animal' and needs an 'override' modifier.
    • The declared type picks what you can call, the real object picks what runs. If you write val a: Animal = Dog(), then a.speak() still prints Woof, because the call goes to the actual Dog object.
    • Return types. speak() declares no return type, so it returns Unit, Kotlin's "nothing useful" value. A subclass must keep a compatible signature.

    Mixing abstract and concrete members

    An abstract class may also hold ordinary members: constructor parameters, properties and functions with bodies. Subclasses inherit them as they are. Only the members marked abstract must be overridden. Properties can be abstract as well:

    abstract class Shape {
        abstract val sides: Int
        fun label() = "shape with $sides sides"
    }
    
    class Triangle : Shape() {
        override val sides = 3
    }
    
    fun main() {
        println(Triangle().label())
    }
    

    This prints shape with 3 sides. The shared function label() is written once in Shape and relies on the abstract property that Triangle supplies. This pattern, a shared algorithm in the parent with the variable parts left abstract, is the main reason to choose an abstract class.

    An abstract class can have a constructor with parameters too. A subclass then passes the arguments in the parent call, for example class Dog(name: String) : Animal(name) when Animal is declared as abstract class Animal(val name: String).

    Abstract class or interface?

    A Kotlin class can extend only one parent class, but it can implement many interfaces. Choose an abstract class when subclasses should share state or code and form a clear "is a" family. Choose an interface when you only want to describe a capability that unrelated classes can have.

    Common mistakes

    • Forgetting the parentheses in : Animal(). The compiler reports that the type has a constructor and must be initialized.
    • Forgetting override. The function then looks like a new member that hides the parent's, which Kotlin rejects.
    • Not implementing every abstract member. One missing implementation is enough to make the subclass an error.
    • Trying to instantiate the abstract class to test it. Create Dog() instead.
    • Printing with the wrong text. The output must be exactly Woof, with that capital W and no extra characters.

    Key takeaways

    • An abstract class is declared with abstract class and can't be instantiated.
    • Abstract members have no body, and every concrete subclass must implement them with override.
    • Extending a class needs the parent constructor call, as in : Animal().
    • Abstract classes can also carry shared properties and functions with bodies.
    • Calls on an Animal variable run the subclass's version.
    Keep going with KotlinAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free