O que é abstract em Kotlin?

O modificador abstract em Kotlin marca classes e membros que não possuem implementação completa e precisam ser implementados por subclasses. Uma classe abstrata não pode ser instanciada diretamente — ela serve como base para outras classes.

Diferente de interfaces, classes abstratas podem ter construtores, estado interno e métodos concretos junto com os abstratos.

Sintaxe básica

abstract class Forma(val cor: String) {
    abstract fun area(): Double
    abstract fun perimetro(): Double

    fun descricao(): String {
        return "Forma $cor com área ${area()}"
    }
}

class Circulo(cor: String, val raio: Double) : Forma(cor) {
    override fun area() = Math.PI * raio * raio
    override fun perimetro() = 2 * Math.PI * raio
}

class Retangulo(cor: String, val largura: Double, val altura: Double) : Forma(cor) {
    override fun area() = largura * altura
    override fun perimetro() = 2 * (largura + altura)
}

fun main() {
    val circulo = Circulo("vermelho", 5.0)
    println(circulo.descricao()) // Forma vermelho com área 78.53...

    val retangulo = Retangulo("azul", 4.0, 6.0)
    println(retangulo.descricao()) // Forma azul com área 24.0
}

Propriedades abstratas

Além de funções, propriedades também podem ser abstratas:

abstract class Veiculo {
    abstract val velocidadeMaxima: Int
    abstract val tipo: String

    fun info() = "$tipo - Velocidade máx: $velocidadeMaxima km/h"
}

class Carro : Veiculo() {
    override val velocidadeMaxima = 200
    override val tipo = "Carro"
}

class Bicicleta : Veiculo() {
    override val velocidadeMaxima = 40
    override val tipo = "Bicicleta"
}

Classes abstratas não precisam de open

Classes abstratas já são implicitamente open, então subclasses podem herdá-las sem precisar marcar nada extra. Membros abstratos também são automaticamente open.

Abstract class vs Interface

AspectoAbstract ClassInterface
ConstrutorSimNão
Estado (campos)SimNão (só propriedades)
Herança múltiplaNãoSim
Métodos concretosSimSim

Use classes abstratas quando suas subclasses compartilham estado e comportamento base. Para contratos puros sem estado, prefira interfaces.