Inheritance adalah mekanisme OOP yang memungkinkan sebuah class mewarisi struktur dan perilaku dari class lain. Class yang diwariskan disebut superclass, sementara class yang mewarisi disebut subclass. Subclass otomatis memiliki property dan method milik superclass, dan dapat menambah perilaku baru atau mengganti yang sudah ada. Pada chapter ini kita akan membuka hierarki class sederhana Hewan → Kucing/Anjing, melihat peran keyword open dan override, serta mengamati polymorphism dalam loop.

Mengapa Inheritance Diperlukan #

Tanpa inheritance, setiap class yang serupa harus menulis ulang property dan method yang sama. Class Kucing, Anjing, dan Burung masing-masing akan memiliki property nama dan method deskripsi() yang identik. Ketika hierarki tumbuh, duplikasi ini menjadi sumber bug — perubahan pada satu class tidak otomatis merambat ke class lain.

Inheritance memecahkan masalah ini dengan menempatkan perilaku umum di superclass dan perilaku khusus di subclass. Subclass cukup menulis bagian yang berbeda, sementara bagian yang sama otomatis tersedia dari superclass. Perubahan pada superclass langsung berlaku untuk seluruh subclass.

Sintaks Inheritance Kotlin #

Kotlin menerapkan inheritance secara eksplisit. Tiga aturan utama:

  1. Class default bersifat final — tidak dapat diwariskan. Untuk mengizinkan inheritance, tandai superclass dengan keyword open.
  2. Subclass menandai pewarisan dengan tanda titik dua, diikuti nama superclass dan pemanggilan constructor-nya: class Kucing(nama: String) : Hewan(nama).
  3. Method yang dapat di-override juga harus ditandai open pada superclass. Subclass menandai override dengan keyword override.
kotlin Contoh: kerangka inheritance
open class Hewan(val nama: String) {
    open fun bersuara(): String = "$nama bersuara"
}

class Kucing(nama: String) : Hewan(nama) {
    override fun bersuara(): String = "$nama mengeong"
}

Pemanggilan : Hewan(nama) pada header class Kucing berarti constructor Kucing mendelegasikan argumen nama ke constructor Hewan. Setelah superclass selesai diinisialisasi, constructor subclass melanjutkan. Subclass otomatis memiliki property nama dari superclass.

Contoh Lengkap Hierarki Hewan #

Contoh berikut mendefinisikan superclass Hewan dengan property nama dan dua method — satu open (bersuara) dan satu final (deskripsi). Subclass Kucing dan Anjing meng-override bersuara dengan implementasi masing-masing, sementara method deskripsi diwarisi apa adanya.

kotlin
// inheritance.kt
// Mendemonstrasikan inheritance dengan open class, override method, dan super.

open class Hewan(val nama: String) {
    open fun bersuara(): String {
        return "$nama mengeluarkan suara umum"
    }

    fun deskripsi(): String {
        return "Hewan: $nama"
    }
}

class Kucing(nama: String) : Hewan(nama) {
    override fun bersuara(): String {
        return "$nama mengeong: Meong!"
    }
}

class Anjing(nama: String, val ras: String) : Hewan(nama) {
    override fun bersuara(): String {
        return "$nama ($ras) menggonggong: Guk guk!"
    }
}

fun main() {
    val kucing = Kucing("Miko")
    val anjing = Anjing("Rex", "Husky")

    println(kucing.deskripsi())
    println(kucing.bersuara())
    println(anjing.deskripsi())
    println(anjing.bersuara())

    println()
    println("Loop polimorfik:")
    val daftar: List<Hewan> = listOf(kucing, anjing)
    for (h in daftar) {
        println("- ${h.bersuara()}")
    }
}

Output yang Dihasilkan:

text
Hewan: Miko
Miko mengeong: Meong!
Hewan: Rex
Rex (Husky) menggonggong: Guk guk!

Loop polimorfik:
- Miko mengeong: Meong!
- Rex (Husky) menggonggong: Guk guk!

Mari kita bedah perilaku inheritance pada kode tersebut:

  1. open class Hewan(val nama: String): keyword open mengizinkan Hewan diwariskan. Tanpa open, kompilator akan menolak deklarasi subclass.
  2. open fun bersuara(): String: method ditandai open sehingga subclass dapat menggantinya. Method deskripsi tidak ditandai open, sehingga tidak dapat di-override.
  3. class Kucing(nama: String) : Hewan(nama): subclass mewarisi Hewan. Tanda titik dua diikuti pemanggilan constructor superclass. Constructor Kucing menerima nama dan meneruskannya ke constructor Hewan.
  4. override fun bersuara(): String: keyword override menandai method yang menggantikan implementasi superclass. Saat runtime, pemanggilan kucing.bersuara() akan memilih implementasi Kucing meskipun variabel bertipe Hewan.
  5. class Anjing(nama: String, val ras: String) : Hewan(nama): subclass dapat menambah property baru (ras) yang tidak ada di superclass. Property ras hanya tersedia pada instance Anjing, bukan Hewan secara umum.
  6. val daftar: List<Hewan> = listOf(kucing, anjing): variabel bertipe List<Hewan> dapat menampung object Kucing dan Anjing. Loop for (h in daftar) memanggil h.bersuara() dan runtime memilih implementasi yang sesuai — ini adalah polymorphism atau dynamic dispatch.

Polymorphism Melalui Referensi Superclass #

Salah satu kekuatan utama inheritance adalah polymorphism. Variabel bertipe superclass dapat menampung object subclass apa pun. Saat method open dipanggil melalui variabel tersebut, runtime menentukan implementasi yang sesuai berdasarkan tipe asli object, bukan tipe deklarasi variabel.

Pada loop for (h in daftar), variabel h bertipe Hewan. Namun pemanggilan h.bersuara() menghasilkan teks "Miko mengeong: Meong!" untuk object Kucing dan "Rex (Husky) menggonggong: Guk guk!" untuk object Anjing. Pemilihan implementasi ini dilakukan secara dinamis saat runtime, bukan saat kompilasi.

Aturan Inheritance Penting #

Beberapa aturan yang perlu diingat saat bekerja dengan inheritance Kotlin:

  • Semua class secara default final. Untuk mewariskan, superclass harus open.
  • Method juga secara default final. Untuk dapat di-override, method harus open.
  • Keyword override wajib di subclass. Tanpa override, method dengan nama sama akan menutup (shadow) method superclass alih-alih menggantikannya secara virtual.
  • Sebuah subclass tetap dapat memanggil implementasi superclass melalui keyword super (mis. super.bersuara()).
  • Kelas hanya dapat mewarisi satu superclass langsung. Pewarisan ganda melalui interface akan dibahas pada chapter Interfaces.

Referensi Lanjutan #

  • Inheritance — panduan resmi inheritance dengan keyword open dan override

Ringkasan #

Inheritance di Kotlin bersifat eksplisit — superclass wajib ditandai open, subclass menandai pewarisan dengan titik dua dan pemanggilan constructor superclass. Method yang dapat di-override juga ditandai open, dan subclass menandai override dengan keyword override. Polymorphism terjadi otomatis saat method open dipanggil melalui referensi superclass. Pada chapter open Classes dan Methods berikutnya, kita akan menelusuri lebih dalam mengapa Kotlin memilih class final sebagai default dan implikasi desain yang menyertainya.