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