Langsung ke konten
KamusNgoding
Menengah Java 3 menit baca

Inheritance dan Polymorphism di Java

#java #inheritance #polymorphism #extends #implements #abstract #interface #override

Java memiliki pendekatan OOP yang sangat ketat dan konsisten — single inheritance untuk class, multiple interface, dan semua method virtual secara default. Ini berbeda dari C++ yang memungkinkan multiple inheritance class, dan mirip dengan C# tapi dengan perbedaan sintaks. Di artikel ini kita akan mempelajari cara membangun hierarki class di Java.

Inheritance dengan extends

// Superclass (parent class)
public class Hewan {
    protected String nama;
    protected int umur;

    public Hewan(String nama, int umur) {
        this.nama = nama;
        this.umur = umur;
    }

    public void makan() {
        System.out.println(nama + " sedang makan.");
    }

    public String getInfo() {
        return String.format("%s (umur %d tahun)", nama, umur);
    }
}

// Subclass menggunakan extends
public class Anjing extends Hewan {
    private String ras;

    public Anjing(String nama, int umur, String ras) {
        super(nama, umur); // Wajib panggil constructor superclass pertama
        this.ras = ras;
    }

    public void gonggong() {
        System.out.println(nama + " (" + ras + "): Guk guk!");
    }

    @Override // Annotation — compiler verifikasi bahwa ini memang override
    public String getInfo() {
        return super.getInfo() + " | Ras: " + ras;
    }
}

// Main.java
Anjing anjing = new Anjing("Buddy", 3, "Labrador");
anjing.makan();         // Mewarisi dari Hewan
anjing.gonggong();      // Method sendiri
System.out.println(anjing.getInfo()); // Override dari Hewan

// Output:
// Buddy sedang makan.
// Buddy (Labrador): Guk guk!
// Buddy (umur 3 tahun) | Ras: Labrador

Polymorphism dan Upcasting

public class Kucing extends Hewan {
    public Kucing(String nama, int umur) { super(nama, umur); }

    @Override
    public String getInfo() { return super.getInfo() + " (Kucing)"; }
}

// Upcasting: subclass bisa disimpan dalam referensi superclass
Hewan h1 = new Anjing("Max", 2, "Poodle");   // Anjing IS-A Hewan
Hewan h2 = new Kucing("Mochi", 1);            // Kucing IS-A Hewan

Hewan[] hewan_hewan = { h1, h2, new Anjing("Rex", 4, "German Shepherd") };

for (Hewan h : hewan_hewan) {
    System.out.println(h.getInfo()); // Polimorfis: memanggil versi yang tepat
    h.makan();
}

// Downcasting (harus hati-hati)
if (h1 instanceof Anjing anjing) { // Pattern matching instanceof (Java 16+)
    anjing.gonggong(); // Akses method Anjing setelah verifikasi tipe
}

Abstract Class

public abstract class Pegawai {
    protected String nama;
    protected double gajiPokok;

    public Pegawai(String nama, double gajiPokok) {
        this.nama = nama;
        this.gajiPokok = gajiPokok;
    }

    // Abstract method: WAJIB diimplementasikan subclass
    public abstract double hitungGaji();
    public abstract String getJabatan();

    // Non-abstract: shared untuk semua subclass
    public void cetakSlipGaji() {
        System.out.println("=== Slip Gaji ===");
        System.out.printf("Nama    : %s%n", nama);
        System.out.printf("Jabatan : %s%n", getJabatan());
        System.out.printf("Gaji    : Rp %,.0f%n", hitungGaji());
    }
}

public class PegawaiTetap extends Pegawai {
    private double tunjangan;

    public PegawaiTetap(String nama, double gajiPokok, double tunjangan) {
        super(nama, gajiPokok);
        this.tunjangan = tunjangan;
    }

    @Override
    public double hitungGaji() { return gajiPokok + tunjangan; }

    @Override
    public String getJabatan() { return "Pegawai Tetap"; }
}

public class Kontrak extends Pegawai {
    private int jamKerja;

    public Kontrak(String nama, double tarifPerJam, int jam) {
        super(nama, tarifPerJam);
        this.jamKerja = jam;
    }

    @Override
    public double hitungGaji() { return gajiPokok * jamKerja; }

    @Override
    public String getJabatan() { return "Karyawan Kontrak"; }
}

// new Pegawai("Ali", 5000000); // ❌ Error: abstract class!

PegawaiTetap pt = new PegawaiTetap("Ali", 8_000_000, 2_000_000);
Kontrak k = new Kontrak("Budi", 150_000, 40);

pt.cetakSlipGaji();
k.cetakSlipGaji();
// Output:
// === Slip Gaji ===
// Nama    : Ali
// Jabatan : Pegawai Tetap
// Gaji    : Rp 10.000.000
// === Slip Gaji ===
// Nama    : Budi
// Jabatan : Karyawan Kontrak
// Gaji    : Rp 6.000.000

Interface di Java

// Interface mendefinisikan kontrak — class WAJIB implementasi semua methodnya
public interface Bisa_Terbang {
    void terbang();
    double getKetinggianMaks();

    // default method (Java 8+) — bisa punya implementasi!
    default String deskripsiTerbang() {
        return "Bisa terbang hingga " + getKetinggianMaks() + " meter";
    }
}

public interface Bisa_Berenang {
    void renang();
}

// Class bisa implements banyak interface (berbeda dengan extends yang hanya 1)
public class Bebek extends Hewan implements Bisa_Terbang, Bisa_Berenang {
    public Bebek(String nama, int umur) { super(nama, umur); }

    @Override
    public void terbang() { System.out.println(nama + ": Wek wek (terbang pendek)"); }

    @Override
    public double getKetinggianMaks() { return 50.0; }

    @Override
    public void renang() { System.out.println(nama + ": Berenang di danau"); }
}

Bebek b = new Bebek("Donald", 2);
b.terbang();
b.renang();
System.out.println(b.deskripsiTerbang()); // default method
// Output:
// Donald: Wek wek (terbang pendek)
// Donald: Berenang di danau
// Bisa terbang hingga 50.0 meter

Pertanyaan yang Sering Diajukan

Apa perbedaan extends dan implements di Java?

extends digunakan untuk mewarisi class (hanya boleh satu class) atau memperluas interface (boleh lebih dari satu). implements digunakan saat class mengimplementasikan satu atau lebih interface. Sebuah class bisa sekaligus menggunakan keduanya: class Bebek extends Hewan implements Bisa_Terbang, Bisa_Berenang.

Mengapa semua method di Java bersifat virtual secara default?

Ini adalah keputusan desain Java untuk mendukung polymorphism sepenuhnya. Di C++, kamu harus eksplisit menandai method sebagai virtual. Di Java, semua method instance bisa di-override oleh subclass tanpa kata kunci tambahan — kamu hanya perlu @Override. Jika ingin mencegah override, gunakan final pada method.

Apa manfaat default method pada interface (Java 8+)?

Sebelum Java 8, menambahkan method baru ke interface yang sudah banyak diimplementasikan berarti semua class yang mengimplementasikannya harus menambahkan implementasi baru — breaking change. default method memungkinkan kamu menambahkan method baru ke interface dengan implementasi default, sehingga class yang sudah ada tidak perlu diubah.

Kapan menggunakan abstract class vs interface di Java?

Gunakan abstract class saat kamu ingin berbagi kode (implementasi) antar class yang saling berhubungan erat, atau saat perlu field (state) dan constructor. Gunakan interface saat mendefinisikan kontrak perilaku yang bisa diterapkan ke class yang tidak saling berhubungan. Aturan praktis: jika hubungannya “IS-A” dengan shared state, gunakan abstract class; jika “CAN-DO” (bisa terbang, bisa berenang), gunakan interface.

Kesimpulan

KonsepJavaC#C++
Inheritanceextends (max 1 class): BaseClass: public Base
Interfaceimplements (banyak): IInterfacePure abstract class
Virtual default✅ Semua methodvirtual keyword❌ (harus eksplisit)
Override marker@Override annotationoverride keywordoverride keyword
Abstract methodabstract keywordabstract keyword= 0 (pure virtual)
Prevent inheritfinalsealedTidak ada keyword

Artikel sebelumnya: Class dan Object di Java — membuat class dasar di Java.

Langkah selanjutnya: Exception Handling di Java — cara menangani error dengan try/catch/throw, termasuk konsep checked vs unchecked exception yang unik di Java.

Artikel Terkait