Pewarisan

Pewarisan dengan Inherits, penimpaan dengan Overrides, dan MyBase.

Daftar isi

Pewarisan (inheritance) adalah mekanisme membentuk kelas baru dari kelas yang sudah ada, sehingga kelas baru mewarisi seluruh anggota kelas induknya tanpa menulis ulang definisinya. Topik ini membahas pernyataan Inherits, penimpaan perilaku dengan Overridable dan Overrides, pemanggilan anggota induk melalui MyBase, serta batasan bahwa satu kelas hanya boleh mewarisi satu kelas induk. Contoh yang dijalankan membangun hierarki armada kantor dengan kelas induk KendaraanKantor dan dua kelas turunannya, lengkap dengan diagram hubungannya.

Relasi kelas induk dan kelas turunan#

Kelas turunan dibentuk dengan pernyataan Inherits NamaKelas di baris pertama badannya. Seluruh anggota Public dan Protected dari kelas induk otomatis tersedia pada turunannya, sehingga properti NomorArmada yang dideklarasikan pada KendaraanKantor langsung dapat digunakan oleh MobilKantor tanpa deklarasi ulang. Turunan juga bebas menambahkan anggota baru yang hanya dimilikinya, seperti properti KapasitasPenumpang pada MobilKantor. Relasi ini menyatakan hubungan “adalah sebuah”, misalnya mobil kantor adalah sebuah kendaraan kantor, dan hubungan itulah yang menjadi ukuran apakah pewarisan cocok untuk dua kelas tertentu.

Diagram berikut merangkum hierarki pada contoh topik ini, yaitu satu kelas induk dengan dua kelas turunan yang masing-masing menulis ulang satu metode.

Hierarki pewarisan KendaraanKantorKendaraanKantordiwarisi dua kelas turunanMobilKantorMotorKantorOverrides DeskripsiTugasOverrides DeskripsiTugas
Hierarki pewarisan armada kantor

Arah pewarisannya sepihak. Kelas turunan mengetahui kelas induknya dan menggunakan anggotanya, sedangkan kelas induk tidak mengetahui turunannya sama sekali. Konsekuensinya, kelas KendaraanKantor dapat dikompilasi tanpa MobilKantor dan MotorKantor, sedangkan kelas turunan tidak dapat berdiri tanpa induknya. Dengan sifat ini, perubahan pada kelas induk menyebar ke seluruh turunannya, yang berguna ketika aturan umum berubah tetapi berbahaya apabila perubahannya menghancurkan asumsi yang dipegang turunannya.

Anggota kelas secara bawaan tidak boleh ditulis ulang oleh turunan. Untuk membukanya, kelas induk menandai anggotanya dengan Overridable, sedangkan kelas turunan menandai penulis ulangannya dengan Overrides dan wajib menggunakan tanda tangan yang sama persis dengan anggota yang ditimpanya. Kombinasi ini disebut penimpaan (overriding), yaitu ketika metode yang sama memiliki perilaku berbeda sesuai kelasnya. Program berikut memperlihatkan satu metode Overridable yang ditimpa oleh dua kelas turunan dengan cara berbeda.

vb Program.vb
Class KendaraanKantor

    Public Property NomorArmada As String

    ' Overridable: kelas turunan boleh menulis ulang metode ini
    Public Overridable Function DeskripsiTugas() As String
        Return $"Armada {NomorArmada} untuk dinas umum kantor"
    End Function

End Class

Class MobilKantor
    Inherits KendaraanKantor

    Public Property KapasitasPenumpang As Integer

    ' Overrides: DeskripsiTugas milik induk ditulis ulang
    Public Overrides Function DeskripsiTugas() As String
        Return MyBase.DeskripsiTugas() & $", kapasitas {KapasitasPenumpang} penumpang"
    End Function

End Class

Class MotorKantor
    Inherits KendaraanKantor

    Public Overrides Function DeskripsiTugas() As String
        Return $"Armada {NomorArmada} untuk pengantaran dokumen antarkantor"
    End Function

End Class

Module Program

    Sub Main()
        Dim mobil As New MobilKantor With {.NomorArmada = "M-01", .KapasitasPenumpang = 5}
        Dim motor As New MotorKantor With {.NomorArmada = "M-02"}
        Dim umum As New KendaraanKantor With {.NomorArmada = "M-00"}

        Console.WriteLine(mobil.DeskripsiTugas())
        Console.WriteLine(motor.DeskripsiTugas())
        Console.WriteLine(umum.DeskripsiTugas())
    End Sub

End Module
text Keluaran
Armada M-01 untuk dinas umum kantor, kapasitas 5 penumpang
Armada M-02 untuk pengantaran dokumen antarkantor
Armada M-00 untuk dinas umum kantor

Tiga pemanggilan DeskripsiTugas menghasilkan tiga keluaran yang berbeda dari satu nama metode yang sama. Objek mobil menjalankan versi MobilKantor yang menggabungkan hasil metode induknya dengan informasi kapasitas, objek motor menjalankan versi yang diganti sepenuhnya, sedangkan objek umum tetap menjalankan versi asli dari KendaraanKantor karena kelas induk tidak menimpa metodenya sendiri. Pola inilah yang disebut polimorfisme, yaitu pemanggilan metode yang sama menghasilkan perilaku sesuai kelas objeknya.

MyBase untuk memanggil anggota induk#

Kata kunci MyBase merujuk pada anggota kelas induk dari dalam kelas turunan. Penggunaan yang paling umum adalah memperluas perilaku alih-alih menggantinya, sebagaimana MobilKantor yang memanggil MyBase.DeskripsiTugas() lalu menambahkan teks kapasitasnya. Tanpa pemanggilan itu, seluruh teks dari induk harus ditulis ulang di turunan, dan setiap perubahan teks induk perlu disalin manual ke semua turunannya.

MyBase juga digunakan pada konstruktor melalui MyBase.New(), yang meneruskan pembentukan objek ke konstruktor kelas induk sebelum badan konstruktor turunan dijalankan. Apabila pernyataan itu tidak dituliskan, compiler menyisipkan MyBase.New() tanpa argumen secara otomatis, sehingga konstruktor induk selalu berjalan dalam penimpaan apa pun. Untuk kelas induk yang konstruktornya berparameter, pemanggilan eksplisit menjadi wajib agar argumen yang diperlukan benar-benar dikirim.

MyBase hanya berlaku di dalam kelas turunan, karena kata kunci itu merujuk pada kelas induk dari kelas tempat kodenya ditulis. Kata kunci pendamping MyClass merujuk pada implementasi milik kelas tempat anggota itu didefinisikan, sehingga pemanggilan lewat MyClass tidak mengikuti penimpaan turunannya, sedangkan Me merujuk objek saat ini yang implementasinya mengikuti penimpaan. Ketiganya menjadi pembeda penting ketika satu nama anggota memiliki versi berbeda pada beberapa tingkat pewarisan.

Batasan pewarisan di VB.NET#

VB.NET mengizinkan tepat satu kelas induk untuk setiap kelas, dan pernyataan Inherits hanya boleh muncul sekali di dalam satu deklarasi Class. Kondisi yang disebut pewarisan ganda pada beberapa bahasa lain tidak didukung, dan compiler menolaknya dengan pesan error BC30121 yang menyatakan Inherits hanya dapat menentukan satu kelas. Kebutuhan menggabungkan kemampuan dari beberapa sumber diselesaikan dengan antarmuka, yang boleh diimplementasikan lebih dari satu oleh kelas yang sama.

vb Contoh: dua Inherits dalam satu kelas ditolak compiler
' tidak-dijalankan
Class Ganda
    Inherits KendaraanKantor
    Inherits ArmadaTerdaftar  ' error BC30121: Inherits hanya boleh muncul satu kali dan menentukan satu kelas
End Class

Batasan lain menyertai tipe nilai. Structure tidak dapat mewarisi maupun diwarisi, karena struktur hanya dapat mengimplementasikan antarmuka. Selain itu, kelas tidak boleh mewarisi dirinya sendiri maupun kelas turunannya, sehingga rantai pewarisan selalu membentuk pohon yang bergerak dari induk ke turunan tanpa lingkaran. Struktur pohon inilah yang membuat compiler dapat menentukan anggota mana yang berasal dari tingkat mana.

Kesalahan umum#

Kesalahan pertama adalah menandai anggota turunan dengan Overrides padahal anggota induknya tidak diberi Overridable. Compiler menolaknya karena anggota biasa tidak dapat ditimpa, dan perbaikannya ada di sisi induk, yaitu menambahkan Overridable pada anggota yang memang dirancang untuk ditulis ulang. Anggota yang tidak dirancang demikian sebaiknya dibiarkan tetap tertutup, karena membukanya berarti menjanjikan perilaku itu untuk seluruh turunan.

Kesalahan kedua adalah menimpa dengan tanda tangan yang berbeda, misalnya nama parameter atau tipe kembaliannya diubah. Compiler tidak mengenalinya sebagai penimpaan dan menandai baris Overrides sebagai error karena anggota induk yang dirujuk tidak ditemukan. Perbaikannya adalah mencocokkan nama, daftar parameter, dan tipe kembaliannya persis dengan anggota induknya, lalu menambahkan perbedaan perilaku di dalam badan metodenya.

Kesalahan ketiga adalah mengganti metode Overridable di turunan tanpa memanggil versi induknya, padahal isi metode induk itu masih diperlukan. Keluaran program tidak salah secara sintaks, tetapi informasi dari induk hilang dan setiap perubahan pada induk tidak pernah sampai ke turunan. Apabila isi induk masih relevan, pola MyBase.NamaMetode() pada awal atau akhir badan turunannya menjaga rantai perilakunya tetap utuh.

Ringkasan#

  • Inherits membentuk kelas turunan yang mewarisi anggota kelas induknya, dan satu kelas hanya boleh mewarisi satu kelas induk.
  • Anggota induk yang diberi Overridable dapat ditulis ulang oleh turunan melalui Overrides dengan tanda tangan yang sama, sehingga pemanggilan yang sama menghasilkan perilaku sesuai kelas objeknya.
  • MyBase memanggil anggota induk dari turunan, baik untuk memperluas metode yang ditimpa maupun untuk meneruskan argumen pada konstruktor melalui MyBase.New().

Referensi#