Inheritance Adalah Pemakaian Ulang "Is-A"
Inheritance memungkinkan class baru dibangun di atas class yang sudah ada. Class baru itu, yaitu subclass, otomatis mendapat field dan method dari superclass, lalu menambah atau mengubah apa pun yang dibutuhkannya. Kamu memakainya saat satu tipe merupakan jenis yang lebih spesifik dari tipe lain: Dog adalah Animal, SavingsAccount adalah BankAccount.
Kamu menulisnya dengan kata kunci extends. Semua yang public atau protected di parent tersedia di child tanpa perlu ditulis ulang.
Dog tidak pernah mendeklarasikan name atau eat(), tetapi ia punya keduanya. Itulah intinya: perilaku bersama berada di satu tempat.
super: Menjangkau Parent
Constructor subclass harus memastikan parent-nya disiapkan lebih dulu. Kamu melakukannya dengan super(...), yang memanggil constructor parent dan harus menjadi pernyataan pertama di constructor subclass. Kalau kamu tidak menulisnya, Java diam-diam menyisipkan pemanggilan ke constructor parent yang tanpa argumen, dan kalau parent tidak punya constructor seperti itu, kodenya tidak akan bisa dikompilasi.
Output-nya menunjukkan bahwa constructor parent berjalan sebelum isi constructor child: pembuatan objek mengalir dari puncak hierarki ke bawah.
Override Method
Subclass bisa mengganti method yang diwarisi dengan mendefinisikannya ulang memakai signature yang sama. Ini disebut overriding, dan kamu sebaiknya selalu menandainya dengan @Override. Anotasi itu tidak wajib, tetapi membuat compiler memastikan bahwa kamu memang cocok dengan method milik parent. Ia menangkap salah ketik seperti tostring() alih-alih toString(), yang tanpa anotasi itu akan diam-diam membuat method yang benar-benar baru.
Meskipun array-nya bertipe Animal, setiap elemen menjalankan speak() miliknya sendiri. Java memilih method berdasarkan objek yang sebenarnya saat runtime, bukan tipe yang dideklarasikan pada variabelnya. Itulah fondasi polymorphism.
Memanggil Versi Parent dengan super.method()
Overriding tidak harus membuang pekerjaan parent. Pakai super.method() untuk menjalankan versi yang diwarisi lalu menambahkan sesuatu padanya:
Tanpa super., memanggil log di dalam TimestampLogger.log akan memanggil dirinya sendiri dan berulang tanpa henti. super. secara eksplisit berarti "versi milik parent".
Field yang Diwarisi dan Aksesnya
Subclass bisa melihat member public dan protected milik parent, tetapi tidak yang private. Field private tetap ada di dalam objek, dan method milik parent sendiri bisa menyentuhnya, tetapi subclass tidak bisa merujuknya secara langsung. Pakai protected, salah satu access modifier di Java, saat kamu ingin subclass punya akses sambil tetap menyembunyikan member itu dari kode yang tidak berkaitan.
class Base {
private int secret; // invisible to subclasses
protected int shared; // visible to subclasses
}
class Derived extends Base {
void demo() {
shared = 5; // OK
// secret = 5; // compile error - private to Base
}
}
Ini juga alasan constructor subclass sering wajib memanggil super(...): itulah satu-satunya cara menginisialisasi state private milik parent.
Menghentikan Inheritance dengan final
Kadang sebuah class sama sekali tidak boleh di-extend. String dibuat final persis karena alasan ini. Menandai class sebagai final melarang pembuatan subclass; menandai method sebagai final melarang method itu di-override, tetapi class-nya tetap boleh di-extend.
final class Constants { } // cannot be subclassed
class Config {
final void load() { } // subclasses may extend Config
// but cannot override load()
}
Pakai final saat perilaku sebuah class harus dijamin dan tidak berubah di seluruh program. Ini sinyal "jangan di-extend" yang disengaja, bukan pilihan default.
Jebakan Umum: Utamakan Composition Kalau Bukan "Is-A"
Inheritance memang menggoda karena memakai ulang kode, tetapi ia mengikat child dengan parent secara erat. Kalau hubungannya bukan "is-a" yang sungguhan, misalnya Car yang kebetulan butuh Engine, jangan membuat Car extends Engine. Mobil punya mesin, mobil bukan mesin. Modelkan itu dengan field (composition):
class Car {
private Engine engine = new Engine(); // Car HAS-A Engine
void start() { engine.ignite(); }
}
Pakai inheritance hanya saat subclass memang benar-benar bentuk khusus dari superclass, dan kamu ingin mewarisi sekaligus menggantikan perilakunya.
Berikutnya: Interface
Inheritance dengan extends memberimu satu parent dan implementasi bersama. Tetapi sebuah class hanya bisa meng-extend satu class. Lalu bagaimana caranya memberi kemampuan yang sama kepada class yang tidak saling berhubungan? Untuk itulah interface ada: kontrak yang bisa diimplementasikan oleh banyak class, dan itu topik halaman berikutnya.
Pertanyaan yang sering diajukan
Apa itu inheritance di Java?
Inheritance (pewarisan) memungkinkan satu class (subclass) memakai ulang field dan method dari class lain (superclass) dengan kata kunci extends. Subclass otomatis mendapat member public dan protected milik parent-nya, dan bisa menambah member baru atau mengganti perilaku yang diwarisi dengan overriding. Inheritance memodelkan hubungan "is-a": Dog adalah Animal.
Apa fungsi kata kunci super di Java?
super merujuk ke class parent. super(...) di dalam constructor memanggil constructor parent (dan harus menjadi pernyataan pertama), sedangkan super.method() memanggil versi parent dari method yang sudah kamu override. Dengan begitu subclass bisa membangun di atas logika parent, bukan menggantinya sepenuhnya.
Apa perbedaan overriding dan overloading di Java?
Overriding mendefinisikan ulang method yang diwarisi di dalam subclass dengan signature yang sama, sehingga perilakunya berubah. Tandai dengan @Override. Overloading mendefinisikan beberapa method dengan nama yang sama tetapi daftar parameter yang berbeda di class yang sama. Overriding berkaitan dengan inheritance dan pemilihan method saat runtime; overloading hanyalah dua method yang kebetulan bernama sama.