Ce face open și final
Spre deosebire de Java, în Kotlin o clasă nu poate fi moștenită și o metodă nu poate fi suprascrisă decât dacă o permiți explicit cu open. Implicit, totul este final. Așa clasele nu se schimbă pe neașteptate din cauza unei subclase la care autorul nu s-a gândit.
Moștenirea se scrie cu : și apelul constructorului clasei de bază: class Carte(...) : Produs(...). O metodă open se suprascrie cu override. Un membru marcat override este la rândul lui open pentru subclasele următoare; dacă vrei să oprești lanțul, scrii final override.
final scris explicit pe o clasă sau o metodă obișnuită este redundant (este deja implicit), dar are sens pe override. Clasele abstract și interfețele sunt deschise implicit.
Exemple
Exemplul 1: Clasă open cu metodă open
Produs și pretFinal sunt open, deci Carte le poate moșteni și schimba. eticheta nu este open, dar folosește versiunea potrivită a lui pretFinal.
open class Produs(val nume: String, val pret: Double) {
open fun pretFinal() = pret * 1.21
fun eticheta() = "$nume: %.2f lei".format(pretFinal())
}
class Carte(nume: String, pret: Double) : Produs(nume, pret) {
override fun pretFinal() = pret * 1.11
}
fun main() {
val produse = listOf(Produs("Lampă", 100.0), Carte("Moromeții", 100.0))
produse.forEach { println(it.eticheta()) }
}
Rezultat
Lampă: 121.00 lei
Moromeții: 111.00 lei
Exemplul 2: final override oprește suprascrierea
Vehicul → Masina → Taxi. Masina marchează roti cu final override, deci Taxi mai poate schimba doar descriere.
open class Vehicul {
open fun roti() = 0
open fun descriere() = "vehicul cu ${roti()} roți"
}
open class Masina : Vehicul() {
final override fun roti() = 4
override fun descriere() = "mașină cu ${roti()} roți"
}
class Taxi(val numar: String) : Masina() {
override fun descriere() = "taxi $numar, ${super.descriere()}"
// override fun roti() = 3 // eroare: 'roti' in 'Masina' is final and cannot be overridden
}
fun main() {
println(Vehicul().descriere())
println(Masina().descriere())
println(Taxi("IS-07-TAX").descriere())
}
Rezultat
vehicul cu 0 roți
mașină cu 4 roți
taxi IS-07-TAX, mașină cu 4 roți
Greșeli frecvente
- Moștenirea unei clase fără
open: eroarethis type is final, so it cannot be extended. - Suprascrierea unei metode fără
openîn clasa de bază: eroare'x' in 'Baza' is final and cannot be overridden. - Apelarea unei metode
opendin constructorul clasei de bază: subclasa încă nu și-a inițializat proprietățile, deci metoda suprascrisă poate vedeanullsau 0.
Comenzi înrudite
override și super: override înlocuiește o metodă sau o proprietate moștenită; super apelează versiunea din clasa de bază sau din interfață.abstract: abstract marchează o clasă care nu poate fi creată direct și membri fără implementare, pe care subclasele trebuie să-i scrie.class: class declară o clasă: un tip nou care grupează date (proprietăți) și comportament (metode).interface: interface descrie ce poate face un obiect (metode și proprietăți), fără stare; o clasă poate implementa mai multe interfețe.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.