Inheritance adalah kemampuan sebuah kelas (derived class atau subclass) untuk menurunkan (mewarisi) atribut dan method dari kelas lain (base class atau superclass). Ini merepresentasikan hubungan “is-a” (adalah seorang/sebuah), contohnya Mobilis-aKendaraan.
Tujuannya adalah untuk code reuse dan menghindari logika kondisional yang kompleks. Daripada memiliki satu kelas Kendaraan dengan banyak if-else untuk kategori yang berbeda, lebih baik membuat subclass untuk setiap kategori (Bus, Minibus, dll.) yang mengimplementasikan perilakunya sendiri.
Sintaks & Mode Pewarisan
class Minibus: public Kendaraan { // ... anggota kelas Minibus ...};
Mode pewarisan (public, protected, private) menentukan bagaimana tingkat akses anggota dari base class akan terlihat di derived class. Pewarisan public adalah yang paling umum digunakan.
Polymorphism dan Dynamic Binding
Polymorphism (poly=banyak, morph=bentuk) adalah kemampuan sebuah pointer atau reference bertipe base class untuk menunjuk atau mengacu pada objek dari derived class-nya saat runtime.
Ini memungkinkan Dynamic Binding: proses penentuan versi method mana yang akan dipanggil terjadi pada saat runtime, berdasarkan tipe aktual dari objek yang ditunjuk, bukan tipe statik dari pointernya.
Peran Keyword virtual
Dynamic binding hanya terjadi jika method di base class dideklarasikan dengan keyword virtual. Tanpa virtual, pemanggilan method akan menggunakan static binding, di mana versi base class yang akan selalu dipanggil, mengabaikan tipe objek sebenarnya.
// Di Base classvirtual void f() { std::cout << "base\n"; }// Di Derived classvoid f() override { std::cout << "derived\n"; } // 'override' disarankan// ... Di main()Base* dp = new Derived();dp->f(); // Akan mencetak "derived" karena f() adalah virtual
Fitur Penting dalam Inheritance
Virtual Destructor
Masalah: Jika Anda menghapus objek derived class melalui pointer base class (delete base_ptr;), hanya destructor dari base class yang akan dipanggil jika ia tidak virtual. Ini menyebabkan memory leak jika derived class mengelola sumber dayanya sendiri.
Solusi: Selalu jadikan destructor di base classvirtual jika kelas tersebut dimaksudkan untuk digunakan secara polimorfik.
class Base {public: virtual ~Base() { /* ... */ } // Virtual destructor};
Abstract Base Class (ABC)
Adalah kelas yang tidak bisa diinstansiasi (tidak bisa dibuat objeknya) dan berfungsi sebagai interface untuk kelas turunannya.
Sebuah kelas menjadi abstrak jika memiliki setidaknya satu pure virtual function, yaitu method yang dideklarasikan dengan = 0;.
class Shape {public: virtual void Draw() = 0; // Pure virtual function};
Derived class yang non-abstrak wajib mengimplementasikan semua pure virtual function dari ABC-nya.
Masalah dalam Multiple Inheritance
Diamond Problem: Terjadi ketika sebuah kelas D mewarisi dari dua kelas B dan C, yang keduanya sama-sama mewarisi dari kelas A. Ini menyebabkan D memiliki dua salinan anggota dari A, sehingga terjadi ambiguitas saat mengakses anggota tersebut.
Solusi C++: Menggunakan virtual inheritance. Kelas B dan C harus mewarisi dari A dengan keyword virtual (class B : virtual public A). Ini memastikan kelas D hanya akan memiliki satu salinan anggota dari A.
Summary
Inheritance memungkinkan pembuatan hierarki kelas dengan hubungan “is-a” untuk code reuse dan desain yang bersih. Keyword virtual adalah kunci untuk mengaktifkan polymorphism, di mana pointer base class dapat memanggil method dari derived class saat runtime (dynamic binding).
Untuk manajemen memori yang aman dalam polimorfisme, destructor pada base class harus virtual. Abstract Base Class (ABC) dengan pure virtual function digunakan untuk mendefinisikan interface yang tidak dapat diinstansiasi.
Additional Information (Optional)
override dan final Specifiers (C++11)
C++ modern memperkenalkan keyword override untuk dipasang pada method di derived class. Ini akan membuat compiler memeriksa apakah method tersebut benar-benar meng-override sebuah method virtual dari base class, sehingga mencegah bug akibat salah ketik nama atau signature.
Keyword final bisa digunakan pada method virtual untuk mencegahnya di-override lebih lanjut di kelas turunan, atau pada kelas untuk mencegahnya diwarisi sama sekali.
Komposisi vs. Pewarisan (Composition vs. Inheritance)
Aturan praktis yang sering dianjurkan adalah “utamakan komposisi daripada pewarisan” (prefer composition over inheritance). Gunakan inheritance hanya jika ada hubungan “is-a” yang jelas dan Anda membutuhkan perilaku polimorfik. Untuk hubungan “has-a” (misalnya Mobilhas-aMesin), gunakan komposisi, di mana satu kelas memiliki objek dari kelas lain sebagai atributnya.