Pewarisan

extends dan super serta pertimbangan kapan komposisi lebih unggul.

Daftar isi

Pewarisan membuat satu kelas mewarisi data dan perilaku kelas lain, sehingga bagian yang sama cukup ditulis sekali di induknya. JavaScript menyediakannya lewat kata kunci extends dan super, dengan pemeriksaan tipe lewat instanceof. Topik ini membangun pewarisan satu tingkat pada kendaraan dinas dan memperlihatkan penimpaan metode yang tetap memanggil versi induknya. Pilihan itu lalu dibandingkan dengan komposisi, yaitu penyusunan object dari bagian-bagian kecil yang mandiri, pada satu kebutuhan yang sama. Penutupnya berupa aturan praktis memilih di antara keduanya.

extends dan super#

Kelas anak dideklarasikan dengan extends diikuti nama kelas induknya, dan sejak baris itu seluruh metode induk menjadi milik anaknya juga. Di dalam constructor kelas anak, super(...) menjalankan constructor induknya dengan argumen yang dioper. Aturannya tegas, this tidak boleh disentuh sebelum super dipanggil. Berkas berikut mewariskan KendaraanDinas kepada MobilPatroli dan memeriksa hubungannya dengan instanceof.

js extends-super.js
// extends mewariskan perilaku induk, super menjalankan bagian induknya.

class KendaraanDinas {
  constructor(nomor, tahun) {
    this.nomor = nomor;
    this.tahun = tahun;
  }

  deskripsi() {
    return this.nomor + ", tahun " + this.tahun;
  }
}

class MobilPatroli extends KendaraanDinas {
  constructor(nomor, tahun, daerah) {
    super(nomor, tahun);
    this.daerah = daerah;
  }
}

const mobil = new MobilPatroli("D 9001 AB", 2023, "Bandung Timur");

console.log(mobil.deskripsi());
console.log(mobil.daerah);
console.log(mobil instanceof MobilPatroli);
console.log(mobil instanceof KendaraanDinas);
text Keluaran
D 9001 AB, tahun 2023
Bandung Timur
true
true

Kelas MobilPatroli tidak menulis metode deskripsi sama sekali, tetapi pemanggilannya berjalan karena metode itu diwarisi dari KendaraanDinas. Panggilan super(nomor, tahun) mengisi nomor dan tahun lewat constructor induk, sehingga baris this.daerah = daerah hanya tinggal menambah data khusus mobil patroli. Operator instanceof memeriksa rantai pewarisan, sehingga object hasil MobilPatroli sah dipandang sebagai instansi kedua kelasnya. Diagram berikut menggambarkan rantai pewarisan dari instansi sampai induknya.

Rantai pewarisan kelasmobil (instansi)dibuat dengan newMobilPatroli.prototypeKendaraanDinas.prototypeObject.prototypeextendsextendsPencarian metode bergerak dari kotak kiri ke kanan
Rantai pewarisan dari instansi mobil sampai kelas induknya

Menimpa metode dan memanggil versi induk#

Metode yang ditulis ulang di kelas anak menggantikan versi induknya, perilaku yang disebut penimpaan (override). Pencarian properti menemukan versi anak lebih dulu karena kelas anak berada lebih dekat pada rantai pencariannya. Di dalam versi anak, super.namaMetode() tetap menjangkau versi induk, sehingga perilaku induk bisa dipakai ulang tanpa disalin. Berkas berikut menimpa metode baris untuk laporan perpustakaan.

js timpa-metode.js
// Metode yang ditimpa tetap dapat memanggil versi induknya lewat super.

class Laporan {
  judul() {
    return "Laporan Inventaris";
  }

  baris(nama, jumlah) {
    return nama + " x " + jumlah;
  }
}

class LaporanPerpustakaan extends Laporan {
  baris(nama, jumlah) {
    return super.baris(nama, jumlah) + " eksemplar";
  }
}

const laporan = new LaporanPerpustakaan();

console.log(laporan.judul());
console.log(laporan.baris("Kamus Bahasa Indonesia", 3));
text Keluaran
Laporan Inventaris
Kamus Bahasa Indonesia x 3 eksemplar

Metode baris di kelas anak memanggil super.baris(nama, jumlah) dengan argumen yang sama, lalu hasilnya diberi satuan eksemplar, sehingga aturan pemformatan dasar tetap milik induknya. Metode judul tidak ditimpa, sehingga tetap diwariskan tanpa perubahan apa pun. Pola menimpa lalu memanggil super berguna bila perilaku anak memperluas perilaku induknya, bukan menggantinya sepenuhnya.

Komposisi sebagai alternatif#

Pewarisan memaksa setiap kombinasi kemampuan menjadi satu kelas. Bila armada perlu sirine, sebagian perlu kamera, dan sebagian lagi perlu keduanya, jalur pewarisan menghasilkan kelas Patroli, PatroliKamera, dan seterusnya yang menumpuk seiring bertambahnya kombinasi. Komposisi menawarkan jalan lain, yaitu kemampuan dipasang sesuai kebutuhan tanpa hierarki. Berkas berikut memecahkan kebutuhan yang sama dengan dua cara.

js pewarisan-vs-komposisi.js
// Satu kebutuhan yang sama, ditulis dengan pewarisan dan dengan komposisi.

// Cara pewarisan, setiap kombinasi kemampuan menjadi satu kelas.
class Patroli {
  nyalakan() {
    return "sirine menyala";
  }
}

class PatroliKamera extends Patroli {
  nyalakan() {
    return super.nyalakan() + ", kamera merekam";
  }
}

// Cara komposisi, kemampuan menjadi bagian yang dipasang.
const sirine = { nyalakan: () => "sirine menyala" };
const kamera = { nyalakan: () => "kamera merekam" };

function buatMobil(kemampuan) {
  return {
    nyalakan() {
      return kemampuan.map(k => k.nyalakan()).join(", ");
    }
  };
}

const mobilA = buatMobil([sirine]);
const mobilB = buatMobil([sirine, kamera]);

console.log(new Patroli().nyalakan());
console.log(new PatroliKamera().nyalakan());
console.log(mobilA.nyalakan());
console.log(mobilB.nyalakan());
text Keluaran
sirine menyala
sirine menyala, kamera merekam
sirine menyala
sirine menyala, kamera merekam

Empat baris keluaran menunjukkan kedua cara menghasilkan perilaku yang sama untuk kebutuhan yang sama. Perbedaannya ada pada pertumbuhan kodenya. Menambah kemampuan pada jalur komposisi berarti menulis satu object kecil lalu memasukkannya ke array, tanpa kelas baru. Pada jalur pewarisan, setiap kemampuan baru berpotensi menambah satu kelas turunan per kombinasi. Untuk kemampuan yang saling mandiri seperti ini, komposisi menjaga kode tetap datar dan mudah diganti.

Kapan memakai yang mana#

Pewarisan tepat bila hubungan kedua kelasnya benar-benar hubungan jenis dan turunannya. Mobil patroli adalah kendaraan dinas, dengan data dan perilaku induk yang berlaku penuh pada anaknya, termasuk saat object anak dipakai menggantikan induknya di semua tempat. Hierarkinya juga dangkal, satu atau dua tingkat, sehingga rantai pencariannya mudah diikuti. Bila salah satu syarat itu hilang, komposisi biasanya lebih aman.

Komposisi unggul bila kemampuan yang diinginkan mandiri satu sama lain, bisa berubah saat program berjalan, atau perlu dipakai oleh jenis object yang berbeda-beda. Daftar kemampuan pada buatMobil bisa diisi, dikosongkan, atau ditukar tanpa menyentuh definisi kelas mana pun. Aturan praktis yang lazim dipakai adalah mulai dari komposisi, lalu naik ke pewarisan hanya bila hubungan jenisnya nyata dan dangkal.

Ringkasan#

  • extends mewariskan perilaku induk kepada kelas anak, dan super menjalankan constructor atau metode versi induk.
  • Metode yang ditimpa ditemukan lebih dulu pada kelas anak, sedangkan super.namaMetode() tetap menjangkau versi induknya.
  • instanceof menghasilkan true untuk setiap kelas di rantai pewarisan sebuah object.
  • Komposisi menyusun kemampuan sebagai bagian mandiri dan tumbuh tanpa kelas baru, sehingga lebih unggul untuk kombinasi banyak, sedangkan pewarisan cocok untuk hubungan jenis yang nyata dan dangkal.

Referensi#