Kotlin Abstract Class

A Kotlin abstract class is a special type of class that cannot be instantiated directly and serves as a blueprint for other classes. The abstract keyword in Kotlin is used to declare these classes, which can contain both abstract and concrete members. Unlike regular classes, Kotlin abstract classes are designed to be inherited by subclasses that must implement all abstract methods and properties defined in the parent abstract class.

The primary purpose of Kotlin abstract class is to provide a common template that multiple related classes can extend while enforcing certain methods to be implemented by child classes. This makes Kotlin abstract classes essential for creating well-structured, inheritance-based architectures in Android applications.

Kotlin Abstract Class Syntax and Declaration

To declare a Kotlin abstract class, you use the abstract keyword before the class definition. Here’s the basic syntax for Kotlin abstract class declaration:

abstract class AbstractClassName {
    // Abstract properties
    abstract var abstractProperty: String
    
    // Abstract methods
    abstract fun abstractMethod(): Unit
    
    // Concrete properties
    var concreteProperty: String = "Default Value"
    
    // Concrete methods
    fun concreteMethod() {
        println("This is a concrete method")
    }
}

Key Properties of Kotlin Abstract Class:

1. Cannot Be Instantiated: You cannot create objects directly from a Kotlin abstract class. This is the fundamental characteristic that distinguishes abstract classes from regular classes.

abstract class Vehicle {
    abstract fun start()
}

// This will cause a compilation error
// val vehicle = Vehicle() // Error: Cannot create an instance of an abstract class

2. Can Contain Abstract Members: Kotlin abstract classes can have abstract properties and methods that must be implemented by subclasses.

abstract class Shape {
    abstract val area: Double
    abstract fun calculatePerimeter(): Double
}

3. Can Contain Concrete Members: Unlike interfaces, Kotlin abstract classes can have concrete implementations alongside abstract ones.

abstract class Animal {
    // Concrete property
    var species: String = "Unknown"
    
    // Concrete method
    fun eat() {
        println("Animal is eating")
    }
    
    // Abstract method
    abstract fun makeSound()
}

4. Always Open for Inheritance: Kotlin abstract classes are implicitly open, meaning you don’t need to use the open keyword for inheritance.

abstract class BaseClass {
    abstract fun abstractFunction()
}

// No need for 'open' keyword
class ChildClass : BaseClass() {
    override fun abstractFunction() {
        println("Implementation in child class")
    }
}

Kotlin Abstract Methods and Properties

Abstract Methods in Kotlin

Kotlin abstract methods are function declarations without implementation that must be overridden in subclasses. Here’s how to define and use abstract methods in Kotlin:

abstract class Database {
    // Abstract method without implementation
    abstract fun connect(url: String): Boolean
    
    // Abstract method with parameters
    abstract fun executeQuery(query: String): List<String>
    
    // Concrete method that can use abstract methods
    fun performOperation(query: String) {
        if (connect("database://localhost")) {
            val results = executeQuery(query)
            println("Operation completed with ${results.size} results")
        }
    }
}

Abstract Properties in Kotlin

Kotlin abstract properties define property declarations that subclasses must implement:

abstract class Configuration {
    // Abstract val property
    abstract val serverUrl: String
    
    // Abstract var property
    abstract var timeout: Int
    
    // Concrete property
    val version: String = "1.0"
    
    // Method using abstract properties
    fun displayConfig() {
        println("Server: $serverUrl, Timeout: $timeout, Version: $version")
    }
}

Implementing Kotlin Abstract Class

When you inherit from a Kotlin abstract class, you must implement all abstract members. Here’s a comprehensive example showing Kotlin abstract class implementation:

abstract class MediaPlayer {
    // Abstract properties
    abstract val supportedFormats: List<String>
    abstract var currentVolume: Int
    
    // Abstract methods
    abstract fun play(file: String): Boolean
    abstract fun pause(): Boolean
    abstract fun stop(): Boolean
    
    // Concrete properties
    var isPlaying: Boolean = false
    
    // Concrete methods
    fun getStatus(): String {
        return if (isPlaying) "Playing" else "Stopped"
    }
    
    protected fun validateFormat(file: String): Boolean {
        val extension = file.substringAfterLast(".")
        return supportedFormats.contains(extension)
    }
}

class AudioPlayer : MediaPlayer() {
    // Implementing abstract properties
    override val supportedFormats = listOf("mp3", "wav", "flac")
    override var currentVolume = 50
    
    // Implementing abstract methods
    override fun play(file: String): Boolean {
        if (!validateFormat(file)) {
            println("Unsupported audio format")
            return false
        }
        
        isPlaying = true
        println("Playing audio file: $file at volume $currentVolume")
        return true
    }
    
    override fun pause(): Boolean {
        if (isPlaying) {
            isPlaying = false
            println("Audio paused")
            return true
        }
        return false
    }
    
    override fun stop(): Boolean {
        isPlaying = false
        currentVolume = 0
        println("Audio stopped")
        return true
    }
    
    // Additional concrete method specific to AudioPlayer
    fun adjustBass(level: Int) {
        println("Bass adjusted to level: $level")
    }
}

Kotlin Abstract Class with Constructor

Kotlin abstract classes can have constructors, including primary and secondary constructors:

abstract class Employee(
    val name: String,
    val id: Int
) {
    // Secondary constructor
    constructor(name: String, id: Int, department: String) : this(name, id) {
        this.department = department
    }
    
    var department: String = "General"
    
    // Abstract method
    abstract fun calculateSalary(): Double
    
    // Concrete method
    fun getEmployeeInfo(): String {
        return "Employee: $name (ID: $id) - Department: $department"
    }
}

class Developer(
    name: String,
    id: Int,
    private val experience: Int
) : Employee(name, id, "Engineering") {
    
    override fun calculateSalary(): Double {
        return 50000.0 + (experience * 5000.0)
    }
    
    fun writeCode(language: String) {
        println("$name is writing code in $language")
    }
}

class Manager(
    name: String,
    id: Int,
    private val teamSize: Int
) : Employee(name, id, "Management") {
    
    override fun calculateSalary(): Double {
        return 70000.0 + (teamSize * 2000.0)
    }
    
    fun conductMeeting() {
        println("$name is conducting a team meeting")
    }
}

Kotlin Abstract Class vs Interface

Understanding the differences between Kotlin abstract class and interface is crucial for making the right design decisions:

FeatureKotlin Abstract ClassKotlin Interface
InstantiationCannot be instantiatedCannot be instantiated
State StorageCan store state (properties with values)Cannot store state (properties must be abstract or have custom accessors)
ConstructorCan have constructorsCannot have constructors
InheritanceSingle inheritance onlyMultiple interface implementation
Abstract MembersCan have abstract and concrete membersAll members are abstract by default (except with default implementations)
// Abstract class example
abstract class AbstractVehicle {
    var fuel: Double = 0.0  // Can store state
    abstract fun startEngine()
}

// Interface example
interface VehicleInterface {
    // val fuel: Double = 0.0  // Error: Cannot store state
    val fuel: Double  // Must be abstract
    fun startEngine()
}

Advanced Kotlin Abstract Class Examples

Nested Abstract Classes

Kotlin abstract classes can contain nested abstract classes:

abstract class GameEngine {
    abstract fun render()
    
    abstract class Renderer {
        abstract fun drawSprite(x: Int, y: Int)
        abstract fun drawText(text: String, x: Int, y: Int)
        
        fun clearScreen() {
            println("Screen cleared")
        }
    }
    
    abstract class AudioSystem {
        abstract fun playSound(soundId: String)
        abstract fun stopAllSounds()
    }
}

class Unity3DEngine : GameEngine() {
    override fun render() {
        println("Unity3D rendering frame")
    }
    
    class UnityRenderer : Renderer() {
        override fun drawSprite(x: Int, y: Int) {
            println("Drawing Unity sprite at ($x, $y)")
        }
        
        override fun drawText(text: String, x: Int, y: Int) {
            println("Drawing Unity text '$text' at ($x, $y)")
        }
    }
}

Abstract Class with Generic Types

Kotlin abstract classes support generic parameters:

abstract class Repository<T> {
    abstract fun save(item: T): Boolean
    abstract fun findById(id: String): T?
    abstract fun findAll(): List<T>
    abstract fun delete(id: String): Boolean
    
    protected fun validateItem(item: T): Boolean {
        return item != null
    }
    
    fun count(): Int {
        return findAll().size
    }
}

class UserRepository : Repository<User>() {
    private val users = mutableMapOf<String, User>()
    
    override fun save(item: User): Boolean {
        if (!validateItem(item)) return false
        users[item.id] = item
        return true
    }
    
    override fun findById(id: String): User? {
        return users[id]
    }
    
    override fun findAll(): List<User> {
        return users.values.toList()
    }
    
    override fun delete(id: String): Boolean {
        return users.remove(id) != null
    }
}

data class User(val id: String, val name: String, val email: String)

Complete Working Example: E-commerce System

Here’s a comprehensive example demonstrating Kotlin abstract class usage in an e-commerce context:

// Import statements (if needed)
import kotlin.math.PI

// Abstract base class for products
abstract class Product(
    val id: String,
    val name: String,
    protected var basePrice: Double
) {
    // Abstract properties
    abstract val category: String
    abstract val weight: Double
    
    // Abstract methods
    abstract fun calculatePrice(): Double
    abstract fun getShippingCost(): Double
    
    // Concrete properties
    var isAvailable: Boolean = true
    var description: String = ""
    
    // Concrete methods
    fun displayInfo() {
        println("Product: $name")
        println("Category: $category")
        println("Price: $${calculatePrice()}")
        println("Shipping: $${getShippingCost()}")
        println("Available: $isAvailable")
        if (description.isNotEmpty()) {
            println("Description: $description")
        }
        println("---")
    }
    
    protected fun applyTax(amount: Double): Double {
        return amount * 1.08 // 8% tax
    }
}

// Electronics product implementation
class Electronics(
    id: String,
    name: String,
    basePrice: Double,
    private val warrantyMonths: Int,
    override val weight: Double
) : Product(id, name, basePrice) {
    
    override val category = "Electronics"
    
    override fun calculatePrice(): Double {
        val warrantyFee = warrantyMonths * 10.0
        return applyTax(basePrice + warrantyFee)
    }
    
    override fun getShippingCost(): Double {
        return when {
            weight <= 1.0 -> 5.99
            weight <= 5.0 -> 12.99
            else -> 25.99
        }
    }
    
    fun getWarrantyInfo(): String {
        return "$warrantyMonths months warranty included"
    }
}

// Clothing product implementation
class Clothing(
    id: String,
    name: String,
    basePrice: Double,
    private val size: String,
    override val weight: Double
) : Product(id, name, basePrice) {
    
    override val category = "Clothing"
    
    override fun calculatePrice(): Double {
        val sizePremium = if (size in listOf("XL", "XXL")) 5.0 else 0.0
        return applyTax(basePrice + sizePremium)
    }
    
    override fun getShippingCost(): Double {
        return if (weight <= 0.5) 3.99 else 7.99
    }
    
    fun getSizeInfo(): String {
        return "Available in size: $size"
    }
}

// Books product implementation
class Book(
    id: String,
    name: String,
    basePrice: Double,
    private val pageCount: Int,
    private val isHardcover: Boolean,
    override val weight: Double
) : Product(id, name, basePrice) {
    
    override val category = "Books"
    
    override fun calculatePrice(): Double {
        val hardcoverFee = if (isHardcover) 5.0 else 0.0
        return applyTax(basePrice + hardcoverFee)
    }
    
    override fun getShippingCost(): Double {
        return when {
            weight <= 0.3 -> 2.99
            weight <= 1.0 -> 4.99
            else -> 8.99
        }
    }
    
    fun getBookDetails(): String {
        val coverType = if (isHardcover) "Hardcover" else "Paperback"
        return "$coverType, $pageCount pages"
    }
}

// Shopping cart to manage products
class ShoppingCart {
    private val products = mutableListOf<Product>()
    
    fun addProduct(product: Product) {
        products.add(product)
        println("Added ${product.name} to cart")
    }
    
    fun removeProduct(productId: String) {
        products.removeIf { it.id == productId }
        println("Removed product with ID: $productId from cart")
    }
    
    fun calculateTotal(): Double {
        return products.sumOf { it.calculatePrice() + it.getShippingCost() }
    }
    
    fun displayCart() {
        if (products.isEmpty()) {
            println("Cart is empty")
            return
        }
        
        println("=== Shopping Cart ===")
        products.forEach { it.displayInfo() }
        println("Total: $${String.format("%.2f", calculateTotal())}")
        println("=====================")
    }
    
    fun getProductCount(): Int = products.size
}

// Main function demonstrating the usage
fun main() {
    // Create various products
    val laptop = Electronics(
        id = "E001",
        name = "Gaming Laptop",
        basePrice = 1299.99,
        warrantyMonths = 24,
        weight = 2.5
    ).apply {
        description = "High-performance laptop for gaming and professional work"
    }
    
    val tshirt = Clothing(
        id = "C001",
        name = "Cotton T-Shirt",
        basePrice = 29.99,
        size = "L",
        weight = 0.3
    ).apply {
        description = "100% organic cotton, comfortable fit"
    }
    
    val novel = Book(
        id = "B001",
        name = "Kotlin Programming Guide",
        basePrice = 45.99,
        pageCount = 520,
        isHardcover = true,
        weight = 0.8
    ).apply {
        description = "Comprehensive guide to Kotlin programming"
    }
    
    val smartphone = Electronics(
        id = "E002",
        name = "Flagship Smartphone",
        basePrice = 899.99,
        warrantyMonths = 12,
        weight = 0.2
    ).apply {
        description = "Latest flagship smartphone with advanced features"
    }
    
    // Create shopping cart and add products
    val cart = ShoppingCart()
    
    // Add products to cart
    cart.addProduct(laptop)
    cart.addProduct(tshirt)
    cart.addProduct(novel)
    cart.addProduct(smartphone)
    
    println("\n")
    
    // Display cart contents
    cart.displayCart()
    
    // Demonstrate specific product methods
    println("\n=== Product Specific Information ===")
    println("Laptop warranty: ${laptop.getWarrantyInfo()}")
    println("T-shirt size: ${tshirt.getSizeInfo()}")
    println("Book details: ${novel.getBookDetails()}")
    println("Smartphone warranty: ${smartphone.getWarrantyInfo()}")
    
    // Remove a product
    println("\n")
    cart.removeProduct("C001")
    
    println("\n")
    cart.displayCart()
}

Expected Output:

Added Gaming Laptop to cart
Added Cotton T-Shirt to cart
Added Kotlin Programming Guide to cart
Added Flagship Smartphone to cart


=== Shopping Cart ===
Product: Gaming Laptop
Category: Electronics
Price: $1463.99
Shipping: $25.99
Available: true
Description: High-performance laptop for gaming and professional work
---
Product: Cotton T-Shirt
Category: Clothing
Price: $32.39
Shipping: $3.99
Available: true
Description: 100% organic cotton, comfortable fit
---
Product: Kotlin Programming Guide
Category: Books
Price: $55.07
Shipping: $4.99
Available: true
Description: Comprehensive guide to Kotlin programming
---
Product: Flagship Smartphone
Category: Electronics
Price: $1031.99
Shipping: $5.99
Available: true
Description: Latest flagship smartphone with advanced features
---
Total: $2624.39
=====================

=== Product Specific Information ===
Laptop warranty: 24 months warranty included
T-shirt size: Available in size: L
Book details: Hardcover, 520 pages
Smartphone warranty: 12 months warranty included

Removed product with ID: C001 from cart

=== Shopping Cart ===
Product: Gaming Laptop
Category: Electronics
Price: $1463.99
Shipping: $25.99
Available: true
Description: High-performance laptop for gaming and professional work
---
Product: Kotlin Programming Guide
Category: Books
Price: $55.07
Shipping: $4.99
Available: true
Description: Comprehensive guide to Kotlin programming
---
Product: Flagship Smartphone
Category: Electronics
Price: $1031.99
Shipping: $5.99
Available: true
Description: Latest flagship smartphone with advanced features
---
Total: $2588.03
=====================

This comprehensive example demonstrates how Kotlin abstract classes provide a solid foundation for building complex, inheritance-based systems. The abstract Product class defines the common structure and behavior that all products must have, while concrete implementations like Electronics, Clothing, and Book provide specific implementations for their respective categories.