Pada Chapter Inheritance, constructor BukuFiksi sempat memanggil super(judul, penulis) tanpa kita bedah. Kata kunci super adalah pasangan cermin dari this: this merujuk object aktif, sedangkan super menjadi jalan menuju superclass — baik untuk memanggil constructor superclass, maupun untuk mengakses field dan method superclass dari dalam subclass. Peran pertamanya bahkan bukan sekadar fasilitas, melainkan keharusan: setiap object subclass harus menjalankan constructor superclass sebelum dirinya selesai diinisialisasi. Pada Chapter ini kita bedah mekanisme super(...), aturan penempatannya yang ketat, lalu konsekuensi galat yang terjadi bila pemanggilan tersebut hilang.

super() Merangkai Constructor Superclass #

Proses new BukuFiksi(...) sebenarnya merangkai dua lapis inisialisasi: constructor Buku harus selesai mengisi judul dan penulis sebelum constructor BukuFiksi melanjutkan dengan genre. Perpindahan antar-lapis tersebut terjadi lewat panggilan super(...) — dan Java menjaga urutannya dengan satu aturan tanpa kompromi: super(...) wajib menjadi pernyataan pertama dalam badan constructor subclass. Mari kita lihat keduanya:

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

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

    public String getJudul() {
        return judul;
    }

    public String deskripsi() {
        return "Buku: " + judul + " oleh " + penulis;
    }
}
java BukuFiksi.java
class BukuFiksi extends Buku {
    private String genre;

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

    @Override
    public String deskripsi() {
        return super.deskripsi() + " [genre: " + genre + "]";
    }
}

Program pemanggilnya membandingkan object superclass dan object subclass berdampingan:

public class AplikasiSuper {
    public static void main(String[] args) {
        Buku kamus = new Buku("KBBI Edisi V", "Badan Pengembangan Bahasa");
        BukuFiksi laskar = new BukuFiksi("Laskar Pelangi", "Andrea Hirata", "Roman");

        System.out.println(kamus.deskripsi());
        System.out.println(laskar.deskripsi());
    }
}

Output yang Dihasilkan:

text
Buku: KBBI Edisi V oleh Badan Pengembangan Bahasa
Buku: Laskar Pelangi oleh Andrea Hirata [genre: Roman]

Mari kita bedah baris-per-baris bagian-bagian kuncinya:

  1. Baris 5 pada BukuFiksi.java (super(judul, penulis);): pernyataan pertama constructor mengirim dua parameter ke constructor Buku. Kedua field milik superclass kini terisi oleh superclass sendiri — subclass tidak perlu tahu bagaimana data inti diinisialisasi.
  2. Baris 6 (this.genre = genre;): baru setelah lapis superclass selesai, subclass mengisi field tambahannya. Urutan ini menjamin bagian warisan object selalu siap sebelum kode subclass berjalan.
  3. Baris 10 (@Override public String deskripsi()): subclass menimpa method deskripsi() milik superclass — penanda @Override dan seluruh aturan penimpaannya adalah pokok bahasan Chapter Method Overriding.
  4. Baris 11 (super.deskripsi() + " [genre: ...]"): inilah wajah kedua super — memanggil method superclass dari dalam method yang menimpanya. Teks “Buku: Laskar Pelangi oleh Andrea Hirata” disusun oleh kode superclass, lalu subclass cukup melampirkan bagian genre-nya; tidak ada penyusunan teks yang diduplikasi.

Ketika super() Tidak Dipanggil #

Apa yang terjadi bila constructor subclass lupa memanggil super(...)? Compiler tidak membiarkannya begitu saja — compiler diam-diam menyisipkan pemanggilan super() tanpa argumen, dan di sinilah persoalan muncul. Sama seperti kasus default constructor pada Chapter Constructors, penyisipan otomatis hanya cocok bila superclass punya constructor tanpa argumen. Superclass Buku kita hanya memiliki constructor dua parameter, sehingga penyisipan super() mengarah ke kekosongan. Berkas berikut memperagakannya dan sengaja dibiarkan gagal dikompilasi:

public class KonstruktorGagal {
    public static void main(String[] args) {
        BukuFiksiSalah buku = new BukuFiksiSalah(
                "Hujan Bulan Juni", "Sapardi Djoko Damono", "Puisi");
        System.out.println(buku.deskripsi());
    }
}

class BukuFiksiSalah extends Buku {
    private String genre;

    BukuFiksiSalah(String judul, String penulis, String genre) {
        this.genre = genre;
    }

    public String deskripsi() {
        return "Fiksi: " + getJudul();
    }
}

Compiler javac menolaknya dengan pesan verbatim berikut:

text
error: constructor Buku in class Buku cannot be applied to given types;
    BukuFiksiSalah(String judul, String penulis, String genre) {
                                                               ^
  required: String,String
  found:    no arguments
  reason: actual and formal argument lists differ in length

Pesan tersebut menceritakan peristiwa lengkapnya: compiler mencoba memanggil constructor Buku tanpa argumen (found: no arguments), padahal yang tersedia meminta dua String (required: String,String). Dua jalan keluar yang sehat: panggil super(judul, penulis) secara eksplisit di constructor subclass, atau tambahkan constructor tanpa argumen di superclass bila memang ada skenario inisialisasi kosong yang sah.

super untuk Field dan Method #

Wajah super yang tersisa berlaku untuk member non-constructor. Kasus super.method() sudah kita lihat bekerja pada deskripsi(): dari dalam method yang menimpa, kode dapat mengikutsertakan perilaku versi superclass tanpa menduplikasinya. Kasus super.field lebih jarang dan muncul hanya ketika subclass mendeklarasikan field dengan nama yang sama persis dengan field superclass — situasi field shadowing yang sah secara tata bahasa tetapi tidak disarankan:

java Konsep: super.field saat nama field bertabrakan
class Induk {
    protected String nama = "versi superclass";
}

class Anak extends Induk {
    private String nama = "versi subclass";   // menutup field superclass

    void tampilkanDuaNama() {
        System.out.println(nama);        // membaca field subclass
        System.out.println(super.nama);  // membaca field superclass
    }
}

Praktik yang jauh lebih sehat adalah menghindari tabrakan nama sama sekali — subclass cukup memakai field warisan (lazimnya protected) tanpa mendeklarasikan ulang. Dengan begitu super.field nyaris tidak pernah dibutuhkan, sementara super(...) dan super.method() tetap menjadi dua wajah yang dipakai setiap hari dalam kode Java sungguhan.

Rangkaian super(...) mengunci urutan inisialisasi antar class, dan super.method() membuka pola kerja sama antar versi method. Namun pada BukuFiksi.deskripsi() tadi kita menyelinap melakukan hal baru: menimpa method warisan dan menandainya dengan @Override. Penimpaan method memiliki aturan lengkap tersendiri — dari proteksi anotasi, resolusi saat runtime, hingga aturan tipe kembalian dan tingkat akses yang tidak boleh menyempit. Chapter berikutnya mengupasnya satu per satu.

Referensi #

Berkas Sumber

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

AplikasiSuper.java

Unduh berkas
java
public class AplikasiSuper {
    public static void main(String[] args) {
        Buku kamus = new Buku("KBBI Edisi V", "Badan Pengembangan Bahasa");
        BukuFiksi laskar = new BukuFiksi("Laskar Pelangi", "Andrea Hirata", "Roman");

        System.out.println(kamus.deskripsi());
        System.out.println(laskar.deskripsi());
    }
}

Buku.java

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

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

    public String getJudul() {
        return judul;
    }

    public String deskripsi() {
        return "Buku: " + judul + " oleh " + penulis;
    }
}

BukuFiksi.java

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

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

    @Override
    public String deskripsi() {
        return super.deskripsi() + " [genre: " + genre + "]";
    }
}

KonstruktorGagal.java

Unduh berkas
java
public class KonstruktorGagal {
    public static void main(String[] args) {
        BukuFiksiSalah buku = new BukuFiksiSalah(
                "Hujan Bulan Juni", "Sapardi Djoko Damono", "Puisi");
        System.out.println(buku.deskripsi());
    }
}

class BukuFiksiSalah extends Buku {
    private String genre;

    BukuFiksiSalah(String judul, String penulis, String genre) {
        this.genre = genre;
    }

    public String deskripsi() {
        return "Fiksi: " + getJudul();
    }
}