Subclass tidak hanya mewarisi property dan method — subclass juga dapat menggantinya dengan implementasi sendiri melalui keyword override. Di Kotlin, baik method maupun property dapat di-override, dan keduanya mengikuti aturan polymorphism yang sama. Pada chapter ini kita akan melihat cara override property val dengan nilai berbeda, mengubah val menjadi var (yang diizinkan), serta bagaimana property override tetap bekerja secara dinamis saat diakses dari method superclass.
Meng-override Property val #
Property val pada superclass dapat di-override dengan override val pada subclass. Override ini menggantikan nilai maupun cara property dihitung. Karena property Kotlin pada dasarnya adalah pasangan getter (dan setter untuk var), override property sebenarnya menggantikan accessor yang dipanggil.
open class Hewan {
open val nama: String = "Tanpa nama"
}
class Kucing : Hewan() {
override val nama: String = "Kucing"
}Saat variabel bertipe Hewan menampung instance Kucing, pembacaan property nama akan memanggil getter yang di-override — mengembalikan "Kucing". Hal ini terjadi karena property override bersifat polymorphism sama seperti method override.
Aturan Mutabilitas: val ke var Diizinkan #
Kotlin mengizinkan subclass mengganti property val pada superclass dengan property var pada subclass. Arah sebaliknya — var menjadi val — dilarang keras karena dapat melanggar kontrak superclass yang sudah menjanjikan property dapat diubah.
| Arah Override | Status |
|---|---|
val → val | Diizinkan |
val → var | Diizinkan (subclass memperluas kemampuan) |
var → val | Dilarang (menyempitkan kontrak superclass) |
var → var | Diizinkan |
Alasan val → var diizinkan adalah bahwa val sebenarnya adalah subset dari var: property read-only adalah property mutable yang kebetulan tidak menyediakan setter. Menambahkan setter pada subclass tidak melanggar kontrak superclass — superclass tetap hanya memanggil getter.
Meng-override Method #
Override method dilakukan dengan override fun pada subclass, menggantikan implementasi superclass yang ditandai open fun. Body subclass dapat memanggil implementasi superclass melalui keyword super bila diperlukan.
open class Hewan {
open fun bersuara(): String = "..."
}
class Kucing : Hewan() {
override fun bersuara(): String = "Meong"
}Pemanggilan method yang di-override bersifat dinamis — tipe asli object menentukan implementasi yang dipanggil, bukan tipe deklarasi variabel.
Contoh Lengkap Property dan Method Override #
Contoh berikut menggabungkan override property dan method. Superclass Kendaraan memiliki property roda (val) dan method deskripsi() yang membaca property tersebut. Subclass Mobil meng-override kedua anggota, sementara SepedaMotor meng-override property roda menjadi var dan menyediakan method untuk mengubahnya — namun tidak meng-override deskripsi().
// overriding.kt
// Mendemonstrasikan override property val/var dan method; val -> var diizinkan.
open class Kendaraan(val merek: String) {
open val roda: Int = 0
open fun deskripsi(): String {
return "Kendaraan $merek dengan $roda roda"
}
}
class Mobil(merek: String, val tipe: String) : Kendaraan(merek) {
// Override property val dengan val baru (nilai berbeda).
override val roda: Int = 4
override fun deskripsi(): String {
return "Mobil $merek ($tipe), roda=$roda"
}
}
class SepedaMotor(merek: String) : Kendaraan(merek) {
// Override val dengan var — diizinkan karena var lebih longgar dari val.
override var roda: Int = 2
fun tambahRodaCadangan() {
roda = 3
}
}
fun main() {
val m = Mobil("Toyota", "Sedan")
println(m.deskripsi())
println("Property roda: ${m.roda}")
val s = SepedaMotor("Honda")
println(s.deskripsi())
println("Awal roda motor: ${s.roda}")
s.tambahRodaCadangan()
println("Setelah tambahRodaCadangan: ${s.roda}")
println()
println("Loop polimorfik:")
val daftar: List<Kendaraan> = listOf(m, s)
for (v in daftar) {
println("- ${v.deskripsi()} (roda=${v.roda})")
}
}Output yang Dihasilkan:
Mobil Toyota (Sedan), roda=4
Property roda: 4
Kendaraan Honda dengan 2 roda
Awal roda motor: 2
Setelah tambahRodaCadangan: 3
Loop polimorfik:
- Mobil Toyota (Sedan), roda=4 (roda=4)
- Kendaraan Honda dengan 3 roda (roda=3)Mari kita amati interaksi override property dan method:
override val roda: Int = 4padaMobil: propertyrodadi-override dengan nilai tetap4. Pemanggilanm.rodamengembalikan4karena getter override yang dipanggil.override var roda: Int = 2padaSepedaMotor: propertyvalsuperclass di-override menjadivar. Sekarang property dapat diubah melaluitambahRodaCadangan(). Pola ini sah karena subclass memperluas kontrak — superclass tidak kehilangan kemampuan apa pun.- Method
deskripsi()pada superclass membacaroda: implementasi superclassKendaraan.deskripsi()memakai referensiroda. Saat dipanggil pada instanceSepedaMotor, runtime memilih getter propertyrodayang di-override — sehingga setelahtambahRodaCadangan(), pesan menampilkan3 rodameskipun methoddeskripsi()sendiri tidak di-override. Mobilmeng-overridedeskripsi(): subclass menyediakan format teks sendiri. Saat dipanggil, runtime memilih implementasiMobilkarena method bersifat polymorphism.SepedaMotortidak meng-overridedeskripsi(): methoddeskripsi()mengikuti implementasi superclass. Tapi karena propertyrodadi-override, hasil teksnya tetap mencerminkan nilai terbaru property subclass.- Loop polimorfik: variabel
vbertipeKendaraan, namunv.deskripsi()memilih implementasi sesuai tipe asli object (MobilatauSepedaMotor). Inilah bukti bahwa property override bekerja sama dengan method override secara konsisten.
Memanggil Implementasi Superclass dengan super #
Subclass dapat memanggil implementasi superclass melalui super.namaMethod() atau super.namaProperty. Pola ini berguna saat subclass ingin memperluas perilaku superclass alih-alih menggantinya sepenuhnya.
open class Hewan {
open fun bersuara(): String = "Suara umum"
}
class Kucing : Hewan() {
override fun bersuara(): String {
val asli = super.bersuara()
return "$asli, lalu Meong!"
}
}Pemanggilan super.bersuara() mengembalikan implementasi superclass tanpa memicu override subclass lagi. Hasilnya kemudian digabung dengan teks tambahan dari subclass.
Aturan Penting Override #
Beberapa aturan yang perlu diingat:
- Property yang di-override juga harus
opendi superclass. - Tipe property subclass harus kompatibel dengan tipe superclass (mis.
Int→Int, bukanInt→String). - Override property
valmenjadivarmengharuskan subclass menyediakan setter. Kompilator otomatis menyediakan setter default bila tidak ditulis manual. - Override method dengan signature yang berbeda (mis. parameter berbeda) bukan override — itu adalah method baru yang menutup (shadow) method superclass.
Referensi Lanjutan #
- Inheritance — aturan resmi override method dan property pada subclass
Ringkasan #
Property dan method sama-sama dapat di-override dengan keyword override. Property val dapat diubah menjadi var pada subclass karena var lebih longgar; arah sebaliknya dilarang. Property override bersifat polymorphism sehingga method superclass yang membaca property akan mendapatkan nilai dari implementasi subclass. Pada chapter Abstract Classes berikutnya, kita akan melihat bagaimana class abstrak memaksa subclass untuk meng-override method dan property tertentu — sebuah bentuk kontrak yang lebih ketat daripada open.