In Kotlin, an abstract class is a class that cannot be instantiated directly. It is meant to be subclassed.
An abstract method is a method declared without an implementation. Subclasses must override it.
Basic example
abstract class Animal {
abstract fun makeSound()
fun sleep() {
println("Sleeping...")
}
}
class Dog : Animal() {
override fun makeSound() {
println("Woof!")
}
}
fun main() {
val dog = Dog()
dog.makeSound()
dog.sleep()
}
Output:
Woof!
Sleeping...
Key points
1. Use abstract before the class
abstract class Shape
You cannot create an instance of it:
val shape = Shape() // Error
2. Abstract methods have no body
abstract fun area(): Double
A subclass must implement them:
class Circle(val radius: Double) : Shape() {
override fun area(): Double {
return Math.PI * radius * radius
}
}
3. Abstract classes can have regular methods
abstract class Shape {
abstract fun area(): Double
fun describe() {
println("This is a shape")
}
}
4. Abstract properties are allowed
abstract class Vehicle {
abstract val maxSpeed: Int
}
class Car : Vehicle() {
override val maxSpeed: Int = 200
}
5. Abstract classes can have constructors
abstract class Person(val name: String) {
abstract fun work()
}
class Developer(name: String) : Person(name) {
override fun work() {
println("$name writes code")
}
}
Complete example
abstract class Shape(val name: String) {
abstract fun area(): Double
fun printInfo() {
println("$name has area ${area()}")
}
}
class Rectangle(
name: String,
val width: Double,
val height: Double
) : Shape(name) {
override fun area(): Double {
return width * height
}
}
class Circle(
name: String,
val radius: Double
) : Shape(name) {
override fun area(): Double {
return Math.PI * radius * radius
}
}
fun main() {
val shapes = listOf(
Rectangle("Rectangle", 5.0, 3.0),
Circle("Circle", 2.0)
)
for (shape in shapes) {
shape.printInfo()
}
}
Abstract class vs interface
Use an abstract class when you want to share state or constructor logic:
abstract class BaseRepository(val tableName: String) {
abstract fun findAll(): List<String>
}
Use an interface when you mainly want to define behavior:
interface Drawable {
fun draw()
}
A class can extend only one abstract class, but it can implement multiple interfaces:
abstract class Animal
interface Runnable {
fun run()
}
interface Swimmable {
fun swim()
}
class Duck : Animal(), Runnable, Swimmable {
override fun run() {
println("Duck runs")
}
override fun swim() {
println("Duck swims")
}
}
In short: use abstract class for a shared base with common implementation/state, and use abstract fun or abstract val for members subclasses must provide.
