Ce face abstract
O clasă abstract este o clasă „neterminată”: nu poți crea obiecte din ea (Forma() nu compilează), doar din subclasele ei. Ea poate avea membri abstract, fără corp, pe care fiecare subclasă concretă îi implementează cu override. O clasă abstractă este automat open, la fel și membrii ei abstracți.
Spre deosebire de o interfață, o clasă abstractă poate avea constructor și stare (proprietăți cu valori), iar metodele ei obișnuite pot folosi metodele abstracte (șablonul general este scris o dată, detaliile în subclase). O clasă poate moșteni o singură clasă abstractă.
Exemple
Exemplul 1: Forme geometrice
descriere() este scrisă o singură dată în clasa abstractă și folosește aria(), implementată diferit de fiecare formă.
import kotlin.math.PI
abstract class Forma(val nume: String) {
abstract fun aria(): Double
fun descriere() = "$nume cu aria %.2f".format(aria())
}
class Cerc(val raza: Double) : Forma("Cerc") {
override fun aria() = PI * raza * raza
}
class Dreptunghi(val l: Double, val h: Double) : Forma("Dreptunghi") {
override fun aria() = l * h
}
fun main() {
val forme = listOf(Cerc(1.0), Dreptunghi(3.0, 4.5), Cerc(2.5))
forme.forEach { println(it.descriere()) }
println("Aria totală: %.2f".format(forme.sumOf { it.aria() }))
}
Rezultat
Cerc cu aria 3.14
Dreptunghi cu aria 13.50
Cerc cu aria 19.63
Aria totală: 36.28
Exemplul 2: Stare comună și proprietate abstractă
Angajat ține numele și salariul de bază; bonus este abstract și diferă pentru fiecare tip de angajat.
abstract class Angajat(val nume: String, protected val salariuBaza: Int) {
abstract val bonus: Int
fun salariuTotal() = salariuBaza + bonus
}
class Programator(nume: String) : Angajat(nume, 9000) {
override val bonus = 1500
}
class Vanzator(nume: String, val vanzari: Int) : Angajat(nume, 5000) {
override val bonus get() = vanzari / 10
}
fun main() {
val echipa = listOf(Programator("Andrei"), Vanzator("Maria", 42_000))
for (a in echipa) println("${a.nume}: ${a.salariuTotal()} lei")
}
Rezultat
Andrei: 10500 lei
Maria: 9200 lei
Greșeli frecvente
Forma("x"): eroarecannot create an instance of an abstract class.- O subclasă care nu implementează toți membrii abstracți: eroare
class 'X' is not abstract and does not implement abstract base class member. Implementează-i sau marchează și subclasaabstract. - Alegerea unei clase abstracte când nu ai stare comună: o interfață e mai flexibilă, pentru că o clasă poate implementa mai multe interfețe.
Comenzi înrudite
interface: interface descrie ce poate face un obiect (metode și proprietăți), fără stare; o clasă poate implementa mai multe interfețe.open și final: În Kotlin clasele și metodele sunt final implicit; open permite moștenirea sau suprascrierea, iar final o oprește din nou.override și super: override înlocuiește o metodă sau o proprietate moștenită; super apelează versiunea din clasa de bază sau din interfață.sealed class și sealed interface: sealed declară o ierarhie închisă: toate subtipurile sunt cunoscute la compilare, deci when le poate verifica pe toate fără else.private și protected: private ascunde o declarație în clasa sau fișierul ei; protected o face vizibilă și în subclase.