Abstract class adalah class dasar yang ditandai abstract. Class ini tidak bisa dibuat dengan new, dan boleh mendeklarasikan method abstract tanpa isi yang wajib diimplementasikan oleh setiap subclass.
Shape membagikan describe() ke setiap subclass dan memaksa masing-masing menyediakan area(). Tipe Shape[] bisa menampung campuran subclass apa pun.
Abstract Class Tidak Bisa Diinstansiasi
Memanggil new pada abstract class adalah error kompilasi, karena objek yang dihasilkan akan punya method tanpa implementasi:
index.ts(6,11): error TS2511: Cannot create an instance of an abstract class.
Ini aturan saat kompilasi. abstract dihapus dari output, jadi Shape yang dihasilkan adalah class JavaScript biasa, dan kode JavaScript tanpa tipe tetap bisa memanggil new Shape(). Kalau sebuah library butuh pengaman saat runtime, constructor bisa memeriksa new.target:
Method dan Property Abstract
Subclass wajib mengimplementasikan setiap member abstract, atau ikut menjadi abstract. Kalau ada yang terlewat, muncul error TS2515 yang bunyinya kira-kira Non-abstract class 'Square' does not implement inherited abstract member area from class 'Shape', atau TS2654 yang mendaftar semuanya kalau ada beberapa yang terlewat.
Field, getter, dan method semuanya bisa abstract, dan bisa juga protected:
Method abstract tidak punya isi; kalau kamu menulis isinya, muncul error TS1245 (Method 'x' cannot have an implementation because it is marked abstract). Abstract class juga tidak wajib punya member abstract sama sekali: abstract saja sudah cukup untuk mencegah class dibuat secara langsung.
Pola Template Method
Alasan paling umum untuk menulis abstract class: class dasar menetapkan urutan langkah, dan setiap subclass mengisi langkah yang berbeda-beda.
Abstract class bisa generic, seperti di sini, sehingga setiap subclass memilih tipe record-nya sendiri.
Tipe Constructor Abstract
typeof Shape untuk abstract class adalah constructor yang tidak boleh kamu panggil, jadi parameter bertipe typeof Shape tidak bisa menjalankan new c(). Kalau sebuah fungsi perlu menerima abstract class (misalnya untuk mendaftarkannya atau memeriksa instanceof), beri tipe dengan abstract construct signature:
abstract new menerima abstract class maupun class konkret; new biasa hanya menerima class konkret.
Abstract Class vs Interface
| Abstract class | Interface | |
|---|---|---|
| Berisi kode | ya: method, inisialisasi field, constructor | tidak, hanya tipe |
| Ada saat runtime | ya | tidak, dihapus |
instanceof | bisa | tidak mungkin |
| Jumlah yang bisa dipakai satu class | satu (extends) | banyak (implements) |
| Access modifier | private, protected, public | hanya member public |
| Tipe untuk objek biasa | hanya jika tidak punya member private/protected, dan instanceof lalu gagal | ya, nilai apa pun dengan bentuk itu |
Patokannya: pakai interface kalau kamu hanya perlu mendeskripsikan bentuk (kasus paling umum, dan juga berlaku untuk object literal), pakai abstract class kalau subclass berbagi implementasi sungguhan dan kamu ingin compiler memaksa mereka mengisi bagian yang kosong. Keduanya bisa digabung dengan baik: interface untuk kontrak publik, abstract class sebagai satu class dasar praktis yang mengimplementasikannya. Lihat interface vs type untuk perbandingan umum lainnya.
Kesalahan Umum
- Memakai abstract class padahal interface sudah cukup. Kalau class dasar tidak berisi kode, itu sebenarnya interface dengan beban runtime tambahan dan batasan pewarisan tunggal.
- Mencoba
static abstract. Tidak diizinkan. Member static tidak bisa abstract. - Mengira
newpada abstract class menghasilkan error saat runtime. Tidak ada error, kecuali kamu menulis pemeriksaannew.target. - Memanggil method abstract dari constructor class dasar. Method itu berjalan sebelum field milik subclass diinisialisasi, jadi implementasinya melihat field tersebut sebagai
undefined.
Pertanyaan yang sering diajukan
Apa itu abstract class di TypeScript?
Class yang ditandai abstract, tidak bisa dibuat dengan new, dan boleh mendeklarasikan member abstract tanpa implementasi. Subclass wajib mengimplementasikan setiap member abstract. Ini cara untuk berbagi kode sekaligus mewajibkan sebuah bentuk.
Apa bedanya abstract class dan interface di TypeScript?
Abstract class bisa berisi kode sungguhan (method yang sudah diimplementasikan, field dengan nilai awal, constructor) dan tetap ada saat runtime, jadi instanceof bisa dipakai padanya; sebuah class hanya bisa mewarisi satu class. Interface tidak berisi kode, dihapus saat kompilasi, dan sebuah class bisa mengimplementasikan banyak interface. Pakai abstract class untuk berbagi perilaku, interface untuk mendeskripsikan bentuk.
Apakah abstract class bisa punya constructor di TypeScript?
Bisa. Constructor itu berjalan saat subclass memanggil super(...). Kamu tetap tidak bisa memanggil new pada abstract class itu sendiri (TS2511: Cannot create an instance of an abstract class).
Apakah method static bisa abstract di TypeScript?
Tidak. abstract hanya berlaku untuk member instance; static abstract menghasilkan error TS1243 ('static' modifier cannot be used with 'abstract' modifier). Untuk mewajibkan bentuk static, beri tipe pada constructor dengan interface yang memuat member static itu, lalu periksa class-nya terhadap interface tersebut.
Apakah aturan abstract class berlaku saat runtime?
Tidak. abstract dihapus, jadi class hasil kompilasi adalah JavaScript biasa dan kode JavaScript biasa tetap bisa memanggil new padanya. Kalau itu penting, periksa new.target di constructor lalu lempar error.