Pewarisan & Abstract Class
extends, super, override, abstract class, polimorfisme, interface implisit dengan implements, dan kapan memilih komposisi daripada pewarisan.
Pewarisan: "adalah sebuah"
Pewarisan (inheritance) membuat class baru yang mengambil semua sifat class lain, lalu menambah atau mengubahnya. Pakai kata extends. Gunakan hanya jika hubungannya benar-benar "A adalah sebuah B": Kucing adalah Hewan.
class Hewan {
String nama;
Hewan(this.nama);
void bersuara() {
print('$nama bersuara');
}
}
class Kucing extends Hewan {
Kucing(super.nama); // teruskan nama ke constructor induk
@override
void bersuara() {
print('$nama: meong!');
}
}
var k = Kucing('Mimi');
k.bersuara(); // Mimi: meong!
super.namameneruskan parameter ke constructor class induk.@overridemenandai method yang menimpa milik induk (compiler membantu menangkap salah ketik).super.bersuara()memanggil versi milik induk bila masih dibutuhkan.
Polimorfisme
Satu variabel bertipe induk bisa menampung berbagai objek anak, dan method yang dijalankan mengikuti objek aslinya:
class Anjing extends Hewan {
Anjing(super.nama);
@override
void bersuara() => print('$nama: guk!');
}
List<Hewan> kebun = [Kucing('Mimi'), Anjing('Rex'), Hewan('Ikan')];
for (var h in kebun) {
h.bersuara(); // tiap objek bersuara dengan caranya sendiri
}
Kode yang memakai Hewan tidak perlu tahu jenis hewannya. Menambah Burung kelak tidak mengubah kode di atas. Itulah kekuatan polimorfisme.
Abstract class
Class abstrak tidak bisa dibuat objeknya; ia hanya "kerangka" yang wajib dilengkapi anak-anaknya.
abstract class Bentuk {
double luas(); // tanpa isi: wajib diimplementasi anak
void info() { // method biasa boleh ada isinya
print('Luas: ${luas().toStringAsFixed(2)}');
}
}
class Lingkaran extends Bentuk {
final double r;
Lingkaran(this.r);
@override
double luas() => 3.14159 * r * r;
}
class Persegi extends Bentuk {
final double sisi;
Persegi(this.sisi);
@override
double luas() => sisi * sisi;
}
// Bentuk b = Bentuk(); // ERROR: abstract
Bentuk b = Lingkaran(2);
b.info();
Interface implisit: implements
Di Dart, setiap class otomatis juga interface. Dengan implements kamu berjanji menulis ulang semua member-nya, tanpa mewarisi isinya.
abstract class Pengirim {
bool kirim(String pesan);
}
class EmailPengirim implements Pengirim {
@override
bool kirim(String pesan) {
print('Email: $pesan');
return true;
}
}
class SmsPengirim implements Pengirim {
@override
bool kirim(String pesan) {
print('SMS: $pesan');
return true;
}
}
void beritahu(Pengirim p) => p.kirim('Halo!'); // tidak peduli jenisnya
extends | implements | |
|---|---|---|
| Mewarisi isi (kode) | Ya | Tidak |
| Jumlah | Satu class | Banyak class |
| Wajib tulis ulang member | Tidak | Ya, semuanya |
Class modifier Dart 3
| Modifier | Arti singkat |
|---|---|
abstract | Tidak bisa diinstansiasi |
interface | Boleh di-implements, tidak boleh di-extends dari luar berkas |
base | Boleh di-extends, tidak boleh di-implements dari luar |
final | Tidak boleh diwarisi/diimplementasi dari luar berkas |
sealed | Himpunan subtipe tertutup (bab 13) |
Komposisi vs pewarisan
Pewarisan membuat class anak sangat terikat pada induk. Jika hubungannya "memiliki" (Mobil punya Mesin), simpan objek lain sebagai field. Aturan praktis: pilih komposisi lebih dulu, gunakan pewarisan bila benar-benar "adalah sebuah".
Error umum
Missing concrete implementation of 'Bentuk.luas'.→ class anak belum menulis method abstrak.The superclass 'Hewan' doesn't have a zero-argument constructor.→ constructor anak tidak meneruskan parameter kesuper.Abstract classes can't be instantiated.→ mencoba membuat objek dari class abstract.