Bayangkan perpustakaan yang mendefinisikan class Buku, lalu beberapa bulan kemudian harus mendefinisikan BukuFiksi, BukuReferensi, dan BukuDigital — yang semuanya menyimpan judul, penulis, dan tahun terbit dengan cara yang persis sama. Menyalin-tempel kode keempat class berarti setiap perbaikan bug harus diulang empat kali. Inheritance (pewarisan) memutus masalah tersebut: class baru mewarisi seluruh field dan method class lama, lalu hanya menambahkan bagian yang benar-benar berbeda. Pada Chapter ini kita belajar menyusun hierarki Buku → BukuFiksi, memahami posisi protected di dalamnya, dan membuktikan bahwa seluruh hierarki bermuara pada satu akar: class Object.

extends Membangun Relasi Superclass-Subclass #

Kata kunci extends pada deklarasi class menciptakan relasi pewarisan: class yang diwarisi disebut superclass (atau parent class), class yang mewarisi disebut subclass (atau child class). Subclass memperoleh seluruh member non-private milik superclass — field maupun method — seolah-olah member tersebut ditulis ulang di dalam subclass, tanpa satu baris kode pun benar-benar tersalin. Istilah kekerabatan ini memang lazim: relasinya sering disebut relasi IS-A, karena setiap BukuFiksi adalah Buku.

Mari kita susun superclass-nya terlebih dahulu. Class Buku menyimpan data inti dan method penghitung usia terbit:

java Buku.java
class Buku {
    private String judul;
    private String penulis;
    protected int tahunTerbit;

    Buku(String judul, String penulis, int tahunTerbit) {
        this.judul = judul;
        this.penulis = penulis;
        this.tahunTerbit = tahunTerbit;
    }

    public String getJudul() {
        return judul;
    }

    public String getPenulis() {
        return penulis;
    }

    public int usia(int tahunSekarang) {
        return tahunSekarang - tahunTerbit;
    }
}

Perhatikan campuran tingkat aksesnya — ini penerapan langsung Chapter Access Modifiers. Field judul dan penulis tetap private sehingga subclass pun harus melewati getter, sedangkan tahunTerbit sengaja dibuka sebagai protected: subclass boleh menyentuhnya langsung, dunia luar tetap tidak. Subclass-nya kemudian ringkas sekali:

java BukuFiksi.java
class BukuFiksi extends Buku {
    private String genre;

    BukuFiksi(String judul, String penulis, int tahunTerbit, String genre) {
        super(judul, penulis, tahunTerbit);
        this.genre = genre;
    }

    public String getGenre() {
        return genre;
    }

    public String rekomendasi() {
        int usiaBuku = usia(2026);
        return genre + " - " + getJudul() + " (" + tahunTerbit
                + "), terbit " + usiaBuku + " tahun lalu";
    }
}

Hanya genre dan rekomendasi() yang benar-benar baru; seluruh data dan perilaku inti buku tidak ditulis ulang. Pemanggilan super(judul, penulis, tahunTerbit) pada constructor berperan meneruskan inisialisasi data inti ke constructor superclass — mekanismya akan kita bedah tuntas pada Chapter Keyword super.

Bukti Pewarisan dalam Eksekusi #

Program kecil berikut menekan object BukuFiksi dari tiga arah: method warisan, method milik subclass, dan method yang tidak kita tulis di kedua class sama sekali:

public class AplikasiWarisan {
    public static void main(String[] args) {
        BukuFiksi laskar = new BukuFiksi("Laskar Pelangi", "Andrea Hirata", 2005, "Roman");

        System.out.println(laskar.getJudul());
        System.out.println(laskar.rekomendasi());

        System.out.println("Asal class : " + laskar.getClass().getName());
        System.out.println("turunan Object? " + (laskar instanceof Object));
    }
}

Output yang Dihasilkan:

text
Laskar Pelangi
Roman - Laskar Pelangi (2005), terbit 21 tahun lalu
Asal class : BukuFiksi
turunan Object? true

Mari kita bedah tiga arah tersebut satu per satu:

  1. Baris 6 (laskar.getJudul()): method getJudul tidak ada di BukuFiksi — baris ini bekerja karena method public superclass dapat dipanggil lewat object subclass. Kode reuse terjadi secara nyata: satu implementasi, banyak pemakai.
  2. Baris 7 (laskar.rekomendasi()): method milik subclass ini memanggil usia(2026) dan getJudul() tanpa awalan apa pun — dua method warisan dipakai dari dalam subclass seolah miliknya sendiri, termasuk field protected tahunTerbit yang tersentuh langsung di baris penyusun teks.
  3. Baris 9 (laskar.getClass().getName()): tidak satu pun class kita mendefinisikan getClass — method ini diwarisi dari java.lang.Object. Hasil cetaknya BukuFiksi membuktikan method Object bekerja pada object subclass kita.
  4. Baris 10 (laskar instanceof Object): operator instanceof menguji tipe object nyata, dan hasilnya true — setiap BukuFiksi adalah Buku, dan setiap Buku adalah Object.

Satu Parent, Satu Akar #

Dua aturan struktural menaungi seluruh hierarki class Java. Pertama, single inheritance: satu class hanya boleh meng-extends tepat satu superclass — sintaks class C extends A, B {} bahkan tidak ada di tata bahasa Java (compiler melaporkannya sebagai galat sintaks '{'' expected). Kebijakan ini sengaja diambil untuk menghindari kerumitan pewarisan ganda, dan kebutuhan “menggabungkan kemampuan dari beberapa sumber” dilayani oleh interface yang akan kita bahas pada Chapter khusus. Kedua, satu akar bersama: class yang ditulis tanpa extends secara implisit merupakan subclass dari java.lang.Object, sehingga seluruh class di Java — buatan kita maupun pustaka standar — membentuk satu pohon keluarga besar berakar pada Object. Method getClass() pada percobaan kita tadi adalah bukti hidupnya.

Pewarisan memberi subclass seluruh warisan superclass, tetapi satu pertanyaan penting belum terjawab: bagaimana constructor superclass dilibatkan saat subclass dijadikan? Data inti buku harus diinisialisasi oleh class yang memilikinya, dan Java mengaturnya lewat panggilan super(...) — lengkap dengan aturan “wajib pernyataan pertama” dan konsekuensi bila parent tak lagi punya constructor tanpa argumen. Chapter berikutnya mengupasnya sampai ke pesan error-nya.

Referensi #

Berkas Sumber

Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.

AplikasiWarisan.java

Unduh berkas
java
public class AplikasiWarisan {
    public static void main(String[] args) {
        BukuFiksi laskar = new BukuFiksi("Laskar Pelangi", "Andrea Hirata", 2005, "Roman");

        System.out.println(laskar.getJudul());
        System.out.println(laskar.rekomendasi());

        System.out.println("Asal class : " + laskar.getClass().getName());
        System.out.println("turunan Object? " + (laskar instanceof Object));
    }
}

Buku.java

Unduh berkas
java
class Buku {
    private String judul;
    private String penulis;
    protected int tahunTerbit;

    Buku(String judul, String penulis, int tahunTerbit) {
        this.judul = judul;
        this.penulis = penulis;
        this.tahunTerbit = tahunTerbit;
    }

    public String getJudul() {
        return judul;
    }

    public String getPenulis() {
        return penulis;
    }

    public int usia(int tahunSekarang) {
        return tahunSekarang - tahunTerbit;
    }
}

BukuFiksi.java

Unduh berkas
java
class BukuFiksi extends Buku {
    private String genre;

    BukuFiksi(String judul, String penulis, int tahunTerbit, String genre) {
        super(judul, penulis, tahunTerbit);
        this.genre = genre;
    }

    public String getGenre() {
        return genre;
    }

    public String rekomendasi() {
        int usiaBuku = usia(2026);
        return genre + " - " + getJudul() + " (" + tahunTerbit
                + "), terbit " + usiaBuku + " tahun lalu";
    }
}