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.
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")
}
}
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 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")
}
}
}
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")
}
}
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 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")
}
}
Understanding the differences between Kotlin abstract class and interface is crucial for making the right design decisions:
Feature | Kotlin Abstract Class | Kotlin Interface |
---|---|---|
Instantiation | Cannot be instantiated | Cannot be instantiated |
State Storage | Can store state (properties with values) | Cannot store state (properties must be abstract or have custom accessors) |
Constructor | Can have constructors | Cannot have constructors |
Inheritance | Single inheritance only | Multiple interface implementation |
Abstract Members | Can have abstract and concrete members | All 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()
}
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)")
}
}
}
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)
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.