Class Lanjutan: Inheritance, Abstract & implements
Pewarisan (extends, super, override, protected), class abstract, mengikat class pada interface dengan implements, dan memilih antara pewarisan dan komposisi.
Pewarisan (inheritance)
Class bisa mewarisi class lain dengan extends. Turunan otomatis memiliki semua anggota induk dan boleh menambah atau mengganti.
class Hewan {
constructor(public nama: string) {}
suara(): string { return "..." }
kenalan(): string { return `${this.nama} berkata ${this.suara()}` }
}
class Kucing extends Hewan {
suara(): string { return "Miaw" } // mengganti (override) metode induk
}
new Kucing("Tom").kenalan() // "Tom berkata Miaw"
super: memanggil induk
Jika turunan punya constructor sendiri, wajib memanggil super(...) sebelum memakai this:
class Anjing extends Hewan {
constructor(nama: string, public ras: string) {
super(nama) // meneruskan ke constructor Hewan
}
override suara(): string { // 'override' = pengaman: error jika induk tak punya suara()
return "Guk! (" + super.suara() + ")"
}
}
Kata kunci override bersifat opsional tetapi sangat dianjurkan: jika nama metode di induk berubah, TypeScript langsung memperingatkan sehingga override-mu tidak diam-diam jadi metode "yatim".
protected
Seperti private tetapi dapat diakses oleh turunan:
class Karyawan {
protected gaji: number
constructor(gaji: number) { this.gaji = gaji }
}
class Manajer extends Karyawan {
bonus(): number { return this.gaji * 0.2 } // ✅ protected terlihat di turunan
}
new Manajer(10).gaji // ❌ protected: tidak terlihat dari luar
Class abstract
Abstract class adalah kerangka yang tidak boleh dibuat instance-nya langsung. Ia boleh berisi metode abstract (tanpa isi) yang wajib diisi turunannya, plus metode biasa yang dipakai bersama.
abstract class Bentuk {
abstract luas(): number // wajib diimplementasi turunan
info(): string { return `Luas = ${this.luas()}` } // dibagi ke semua turunan
}
class Persegi extends Bentuk {
constructor(private sisi: number) { super() }
luas(): number { return this.sisi ** 2 }
}
new Bentuk() // ❌ Cannot create an instance of an abstract class
new Persegi(4).info() // "Luas = 16"
class Rusak extends Bentuk {} // ❌ belum mengimplementasi luas()
implements: class memenuhi interface
Interface mendeskripsikan "apa yang bisa dilakukan"; class implements interface berjanji memenuhi kontraknya. Class boleh mengimplementasi banyak interface (tetapi hanya mewarisi satu class).
interface Dicetak { cetak(): string }
interface Disimpan { simpan(): void }
class Laporan implements Dicetak, Disimpan {
constructor(private isi: string) {}
cetak(): string { return this.isi }
simpan(): void { console.log("tersimpan") }
}
implements hanya memeriksa; ia tidak menyalin kode apa pun ke class.
Polimorfisme
Karena Persegi, Lingkaran, dan lainnya sama-sama Bentuk, kita bisa menulis kode yang bekerja untuk semuanya:
function totalLuas(daftar: Bentuk[]): number {
return daftar.reduce((t, b) => t + b.luas(), 0)
}
Pewarisan atau komposisi?
| Pewarisan | Komposisi |
|---|---|
| Hubungan "adalah" (Kucing adalah Hewan) | Hubungan "punya" (Mobil punya Mesin) |
| Rantai dalam sulit diikuti | Lebih fleksibel, mudah diganti |
| Cocok untuk hierarki yang stabil | Pilihan awal yang lebih aman |
Aturan umum: utamakan komposisi, gunakan pewarisan hanya bila hubungan "adalah" benar-benar jelas dan hierarkinya dangkal (maksimal 2–3 tingkat).
Kesalahan umum pemula
- Lupa
super()di constructor turunan (error: "Constructors for derived classes must contain a 'super' call"). - Memakai
thissebelumsuper(). - Membuat hierarki pewarisan yang terlalu dalam padahal cukup dengan fungsi atau komposisi.