Abstract Class dan Mixin
Kontrak dengan abstract class, berbagi kemampuan lewat mixin, dan interface implisit.
Abstract class: cetakan yang belum jadi
Kadang class induk terlalu umum untuk dibuat object-nya. Untuk apa bikin object Hewan generik? Yang ada ya kucing atau anjing. Abstract class tidak bisa diinstansiasi, tapi bisa diwarisi:
abstract class Bentuk {
double luas(); // method tanpa badan: wajib diimplementasi anak
}
class Persegi extends Bentuk {
double sisi;
Persegi(this.sisi);
@override
double luas() => sisi * sisi;
}
class Lingkaran extends Bentuk {
double r;
Lingkaran(this.r);
@override
double luas() => 3.14 * r * r;
}
void main() {
// var b = Bentuk(); // ERROR: abstract tidak bisa dibuat object
var daftar = <Bentuk>[Persegi(4), Lingkaran(7)];
for (var b in daftar) {
print(b.luas());
}
}Method tanpa badan seperti double luas(); memaksa setiap anak mengimplementasikannya. Ini namanya kontrak: "kalau kamu mengaku Bentuk, kamu wajib bisa menghitung luas".
Interface implisit: setiap class adalah interface
Di Dart tidak ada keyword interface. Setiap class otomatis bisa dipakai sebagai interface dengan implements:
class Terbang {
void terbang() => print('Terbang tinggi!');
}
class Burung implements Terbang {
@override
void terbang() => print('Mengepakkan sayap...');
}
void main() {
Burung().terbang();
}Bedanya dengan extends: implements tidak mewarisi isi, hanya kontraknya. Semua method harus ditulis ulang. Cocok saat kamu cuma butuh kesepakatan tipe tanpa berbagi implementasi.
Mixin: tempel kemampuan
Ingat batasan single inheritance? Mixin adalah jawabannya. Mixin seperti stiker kemampuan yang bisa ditempel ke class mana pun:
class Hewan {
String nama;
Hewan(this.nama);
}
mixin BisaRenang {
void berenang() => print('Berenang dengan gaya bebas!');
}
mixin BisaTerbang {
void terbang() => print('Terbang melayang!');
}
class Bebek extends Hewan with BisaRenang, BisaTerbang {
Bebek(String nama) : super(nama);
}
void main() {
var d = Bebek('Dodi');
d.berenang();
d.terbang();
}Satu class bisa with banyak mixin sekaligus. Mixin tidak punya constructor dan tidak bisa diinstansiasi sendiri.
Catatan teknis: Urutan mixin itu penting kalau ada method yang sama:
class A with M1, M2maka versi M2 yang menang. Aturan umumnya: mixin yang disebut terakhir menimpa yang sebelumnya. Jarang jadi masalah, tapi wajib tahu kalau suatu hari perilakunya terasa aneh.
Kapan pakai apa?
| Kebutuhan | Pakai |
|---|---|
| Hierarki "adalah" + berbagi kode | extends |
| Kontrak wajib implementasi | abstract class |
| Kontrak tanpa warisi kode | implements |
| Berbagi kemampuan ke banyak class tak berkerabat | mixin |
Contoh nyata: di Flutter, SingleTickerProviderStateMixin ditempel ke State untuk memberi kemampuan animasi. Tanpa mixin, setiap State yang butuh animasi harus extends class khusus dan hierarkinya jadi kaku.
Latihan gabungan
mixin Logger {
void log(String pesan) => print('[LOG] $pesan');
}
abstract class Kendaraan {
void jalan();
}
class Mobil extends Kendaraan with Logger {
@override
void jalan() {
log('Mesin dinyalakan');
print('Mobil melaju...');
}
}
void main() {
Mobil().jalan();
}Di sini Mobil mewarisi kontrak dari Kendaraan sekaligus menempel kemampuan Logger. Tiga konsep dalam satu class kecil.