Kotlin Abstract Classes

Creating base classes with partial implementations

🏗️ What are Abstract Classes?

Abstract classes in Kotlin are classes that cannot be instantiated directly. They serve as base classes with both abstract and concrete methods, providing a foundation for inheritance while enforcing implementation of specific methods in subclasses.


// Abstract class example
abstract class Animal {
    abstract fun makeSound()
    fun sleep() = println("Sleeping...")
}
                                    

Key Abstract Class Features

🚫

Cannot Instantiate

Cannot create objects directly

abstract class Shape
// val shape = Shape() // Error!
📋

Abstract Methods

Methods without implementation

abstract class Animal {
    abstract fun makeSound()
}
⚙️

Concrete Methods

Methods with implementation

abstract class Animal {
    fun eat() = println("Eating...")
}
🏷️

Properties

Both abstract and concrete properties

abstract class Animal {
    abstract val name: String
    val isAlive = true
}

🔹 Basic Abstract Class

Here's how to create and use an abstract class:

// Abstract class declaration
abstract class Vehicle {
    abstract val maxSpeed: Int
    abstract fun start()
    
    // Concrete method
    fun stop() {
        println("Vehicle stopped")
    }
    
    // Concrete property
    val isRunning = false
}

// Concrete implementation
class Car : Vehicle() {
    override val maxSpeed = 200
    
    override fun start() {
        println("Car engine started")
    }
}

fun main() {
    val car = Car()
    car.start()
    car.stop()
    println("Max speed: ${car.maxSpeed} km/h")
}

Output:

Car engine started
Vehicle stopped
Max speed: 200 km/h

🔹 Abstract Class with Constructor

Abstract classes can have constructors and initialization blocks:

abstract class Animal(val name: String) {
    abstract val species: String
    abstract fun makeSound()
    
    init {
        println("Animal $name created")
    }
    
    fun introduce() {
        println("I'm $name, a $species")
        makeSound()
    }
}

class Dog(name: String) : Animal(name) {
    override val species = "Canine"
    
    override fun makeSound() {
        println("Woof! Woof!")
    }
}

fun main() {
    val dog = Dog("Buddy")
    dog.introduce()
}

Output:

Animal Buddy created
I'm Buddy, a Canine
Woof! Woof!

🔹 Abstract vs Interface

Understanding when to use abstract classes vs interfaces:

// Abstract class - for shared implementation
abstract class GameCharacter {
    var health = 100
    abstract val name: String
    
    fun takeDamage(damage: Int) {
        health -= damage
        println("$name took $damage damage. Health: $health")
    }
    
    abstract fun attack()
}

// Interface - for contracts
interface Flyable {
    fun fly()
}

class Hero(override val name: String) : GameCharacter(), Flyable {
    override fun attack() {
        println("$name attacks with sword!")
    }
    
    override fun fly() {
        println("$name flies through the air!")
    }
}

fun main() {
    val hero = Hero("Arthur")
    hero.attack()
    hero.takeDamage(20)
    hero.fly()
}

Output:

Arthur attacks with sword!
Arthur took 20 damage. Health: 80
Arthur flies through the air!

🔹 Abstract Properties

Abstract classes can have abstract properties that must be overridden:

abstract class Shape {
    abstract val area: Double
    abstract val perimeter: Double
    
    fun printInfo() {
        println("Area: $area, Perimeter: $perimeter")
    }
}

class Circle(val radius: Double) : Shape() {
    override val area: Double
        get() = Math.PI * radius * radius
    
    override val perimeter: Double
        get() = 2 * Math.PI * radius
}

class Rectangle(val width: Double, val height: Double) : Shape() {
    override val area = width * height
    override val perimeter = 2 * (width + height)
}

fun main() {
    val circle = Circle(5.0)
    val rectangle = Rectangle(4.0, 6.0)
    
    circle.printInfo()
    rectangle.printInfo()
}

Output:

Area: 78.53981633974483, Perimeter: 31.41592653589793
Area: 24.0, Perimeter: 20.0

🧠 Test Your Knowledge

Can you create an instance of an abstract class directly?