Pada bab-bab sebelumnya, method Bersuara() versi Hewan mencetak pesan generik karena kita belum tahu hewan apa yang sedang dibuat. Untuk beberapa konsep, versi generik seperti itu justru tidak bermakna: class BangunDatar tidak punya luas hingga kita tahu bentuknya. Abstract class menyelesaikan persoalan ini dengan menjadi class yang tidak dapat diinstansiasi dan sengaja dirancang untuk diwarisi.

Deklarasi abstract class dan abstract method #

Kata kunci abstract diletakkan pada deklarasi class dan method:

  • abstract class tidak dapat dibuat object-nya dengan new; class ini hanya berperan sebagai cetak biru untuk turunannya.
  • abstract method hanya berisi deklarasi tanpa badan, dan setiap derived class wajib mengisinya dengan override.
  • Abstract class tetap boleh memiliki member konkret, misalnya property dan method biasa yang langsung diwariskan.

Contoh: BangunDatar dan Turunannya #

csharp
public abstract class BangunDatar
{
    public string Nama { get; }

    protected BangunDatar(string nama)
    {
        Nama = nama;
    }

    public abstract double HitungLuas();

    public void TampilkanLuas()
    {
        Console.WriteLine($"Luas {Nama}: {HitungLuas()}");
    }
}

public class PersegiPanjang : BangunDatar
{
    private double panjang;
    private double lebar;

    public PersegiPanjang(string nama, double panjang, double lebar) : base(nama)
    {
        this.panjang = panjang;
        this.lebar = lebar;
    }

    public override double HitungLuas()
    {
        return panjang * lebar;
    }
}

public class Persegi : BangunDatar
{
    private double sisi;

    public Persegi(string nama, double sisi) : base(nama)
    {
        this.sisi = sisi;
    }

    public override double HitungLuas()
    {
        return sisi * sisi;
    }
}

List<BangunDatar> daftarBangun = new List<BangunDatar>
{
    new PersegiPanjang("Persegi Panjang", 8, 5),
    new Persegi("Persegi", 6)
};

foreach (BangunDatar bangun in daftarBangun)
{
    bangun.TampilkanLuas();
}

Output yang Dihasilkan:

text
Luas Persegi Panjang: 40
Luas Persegi: 36

Mari kita bedah baris demi baris:

  1. public abstract class BangunDatar: Class ini tidak dapat diinstansiasi; kita tidak akan pernah menulis new BangunDatar().
  2. protected BangunDatar(string nama): Constructor bertanda protected agar hanya dapat dipanggil oleh derived class melalui base(nama).
  3. public abstract double HitungLuas();: Method ini hanya deklarasi tanpa badan; setiap turunan wajib mengisi rumus luasnya sendiri.
  4. public void TampilkanLuas(): Member konkret ini diwariskan apa adanya; method ini memanggil HitungLuas() tanpa tahu rumus mana yang berjalan.
  5. override pada PersegiPanjang dan Persegi: Kedua class mengisi deklarasi abstract dengan rumus panjang * lebar dan sisi * sisi.

Kapan Memakai Abstract Class #

Abstract class cocok dipakai ketika:

  • Ada data atau method yang dipakai bersama oleh semua turunan, seperti Nama dan TampilkanLuas() pada contoh di atas.
  • Kita ingin memastikan suatu method pasti diisi oleh setiap turunan, seperti HitungLuas().
  • Class dasarnya tidak masuk akal dijadikan object, misalnya BangunDatar tanpa bentuk konkret.

Bandingkan dengan class biasa: class biasa dapat langsung dibuat object-nya dan tidak menuntut turunan mengisi method apa pun. Abstract class justru menukar kemampuan itu dengan jaminan struktur untuk semua turunannya.

text
error CS0144: Cannot create an instance of the abstract type or interface 'BangunDatar'

Abstract class memadukan dua dunia: member konkret yang dipakai bersama, dan deklarasi abstract yang wajib diisi turunan. Kontrak serupa juga dapat dinyatakan tanpa member konkret sama sekali, melalui interface pada bab berikutnya.