Masukkan Password
42 Memahami Pewarisan (Inheritance)
Lecture ini membahas konsep OOP yang sangat penting, yaitu inheritance (pewarisan).
Kalau disederhanakan, inheritance berarti:
Sebuah class dapat mewarisi property dan method dari class lain, sehingga kita tidak perlu menulis ulang kode yang sama.
Konsep ini akan terasa sangat mudah kalau kita mulai dari masalah yang ingin diselesaikan.
1. Masalah sebelum menggunakan inheritance
Misalkan kita memiliki sebuah class Person.
Seorang person memiliki:
namegenderdateOfBirthcalculateAge()
Contohnya:
class Person {
name: string;
gender: string;
dateOfBirth: string;
calculateAge() {
// menghitung umur
}
}
Sekarang kita ingin membuat class Employee.
Employee juga merupakan seorang person.
Jadi employee juga memiliki:
name
gender
dateOfBirth
calculateAge()
Tetapi employee memiliki tambahan:
salary
bonus
getSalary()
Kalau kita membuatnya secara terpisah:
class Employee {
name: string;
gender: string;
dateOfBirth: string;
salary: number;
bonus: number;
calculateAge() {
// menghitung umur
}
getSalary() {
// menghitung salary
}
}
Kita menulis ulang:
name
gender
dateOfBirth
calculateAge()
Padahal kode tersebut sudah ada di Person.
2. Masalahnya akan semakin besar
Misalnya kita juga punya Athlete.
Athlete memiliki:
name
gender
dateOfBirth
calculateAge()
country
medals
participate()
Sekarang kita punya:
Person
├── name
├── gender
├── dateOfBirth
└── calculateAge()
Employee
├── name ← duplikat
├── gender ← duplikat
├── dateOfBirth ← duplikat
├── calculateAge ← duplikat
├── salary
├── bonus
└── getSalary()
Athlete
├── name ← duplikat
├── gender ← duplikat
├── dateOfBirth ← duplikat
├── calculateAge ← duplikat
├── country
├── medals
└── participate()
Ini disebut code duplication.
Kita menulis kode yang sama berulang kali.
3. Solusinya: inheritance
Karena:
Employee adalah Person.
Dan:
Athlete adalah Person.
Kita bisa membuat Person sebagai parent/base class.
Kemudian Employee dan Athlete menjadi child/derived class.
Strukturnya:
Person
│
┌───────┴───────┐
↓ ↓
Employee Athlete
Person menyimpan bagian yang sama.
Person
│
├── name
├── gender
├── dateOfBirth
└── calculateAge()
Kemudian Employee hanya menyimpan bagian khusus employee:
Employee
│
├── salary
├── bonus
└── getSalary()
Sedangkan Athlete hanya menyimpan bagian khusus athlete:
Athlete
│
├── country
├── medals
└── participate()
Karena Employee dan Athlete mewarisi Person, mereka juga mendapatkan:
name
gender
dateOfBirth
calculateAge()
4. Inilah yang disebut inheritance
Inheritance berarti:
Class baru dapat memperoleh/mewarisi property dan method dari class yang sudah ada.
Class yang diwarisi disebut:
- parent class
- base class
- superclass
Sedangkan class yang mewarisi disebut:
- child class
- derived class
- subclass
Dalam contoh kita:
Person
adalah:
Parent
Base class
Superclass
Sedangkan:
Employee
Athlete
adalah:
Child
Derived class
Subclass
Ketiga istilah tersebut pada dasarnya membahas hubungan yang sama.
5. Cara membuat inheritance di TypeScript
TypeScript menggunakan keyword:
extends
Misalnya:
class Employee extends Person {
}
Bacanya:
EmployeeextendsPerson.
Atau secara sederhana:
Employee mewarisi Person.
Strukturnya:
Employee
│
│ extends
↓
Person
6. Apa yang didapat Employee?
Misalnya:
class Person {
name: string;
gender: string;
dateOfBirth: string;
calculateAge() {
// ...
}
}
Kemudian:
class Employee extends Person {
salary: number;
bonus: number;
getSalary() {
return this.salary + this.bonus;
}
}
Walaupun kita tidak menulis:
name
gender
dateOfBirth
calculateAge()
di dalam Employee, Employee tetap bisa mengakses bagian tersebut karena mewarisi Person.
Secara konsep:
Employee
│
├── salary ← milik Employee
├── bonus ← milik Employee
├── getSalary() ← milik Employee
│
├── name ← diwarisi dari Person
├── gender ← diwarisi dari Person
├── dateOfBirth ← diwarisi dari Person
└── calculateAge() ← diwarisi dari Person
7. Contoh praktis
Mari kita buat Person.
class Person {
name: string;
dateOfBirth: string;
gender: string;
constructor(
name: string,
dateOfBirth: string,
gender: string
) {
this.name = name;
this.dateOfBirth = dateOfBirth;
this.gender = gender;
}
calculateAge() {
const currentYear = new Date().getFullYear();
const birthYear = new Date(this.dateOfBirth).getFullYear();
return currentYear - birthYear;
}
}
Sekarang Person mempunyai:
Properties:
- name
- dateOfBirth
- gender
Method:
- calculateAge()
8. Membuat Employee yang mewarisi Person
Kita tulis:
class Employee extends Person {
salary: number;
bonus: number;
getSalary() {
return this.salary + this.bonus;
}
}
Sekarang Employee mempunyai:
Employee
│
├── name ← dari Person
├── dateOfBirth ← dari Person
├── gender ← dari Person
├── calculateAge() ← dari Person
│
├── salary ← milik Employee
├── bonus ← milik Employee
└── getSalary() ← milik Employee
Perhatikan keuntungannya.
Kita tidak perlu menulis ulang:
name
dateOfBirth
gender
calculateAge()
9. Tapi ada masalah baru: constructor
Sekarang kita ingin membuat object:
const employee = new Employee(...);
Employee memiliki:
name
dateOfBirth
gender
salary
bonus
Kita ingin semua property tersebut diinisialisasi.
Maka constructor Employee menerima semuanya:
class Employee extends Person {
salary: number;
bonus: number;
constructor(
name: string,
dateOfBirth: string,
gender: string,
salary: number,
bonus: number
) {
// ...
}
}
Pertanyaannya:
Bagaimana cara menginisialisasi
name,dateOfBirth, dangenderyang sebenarnya merupakan bagian dariPerson?
Di sinilah kita membutuhkan super().
10. Apa itu super()?
super() digunakan untuk memanggil constructor dari parent class.
Misalnya parent kita:
class Person {
constructor(
name: string,
dateOfBirth: string,
gender: string
) {
this.name = name;
this.dateOfBirth = dateOfBirth;
this.gender = gender;
}
}
Kemudian child:
class Employee extends Person {
constructor(
name: string,
dateOfBirth: string,
gender: string,
salary: number,
bonus: number
) {
super(name, dateOfBirth, gender);
this.salary = salary;
this.bonus = bonus;
}
}
Bagian ini:
super(name, dateOfBirth, gender);
memanggil constructor milik Person.
11. Analogi super()
Bayangkan Person adalah orang tua yang bertugas menyiapkan bagian dasar seseorang:
Person
│
├── nama
├── gender
└── tanggal lahir
Kemudian Employee menambahkan:
Employee
│
├── salary
└── bonus
Ketika membuat Employee:
Buat Employee
│
↓
Siapkan bagian Person
│
↓
super(...)
│
↓
name
gender
dateOfBirth
│
↓
Siapkan bagian Employee
│
↓
salary
bonus
Jadi super() memastikan constructor parent dijalankan terlebih dahulu.
12. Kenapa super() harus dipanggil?
Ini aturan penting dalam class turunan.
Kalau Employee extends Person dan kita membuat constructor sendiri, kita harus memanggil:
super(...)
sebelum menggunakan this untuk property milik Employee.
Misalnya:
constructor(...) {
super(name, dateOfBirth, gender);
this.salary = salary;
this.bonus = bonus;
}
Urutannya harus:
1. super()
2. this.salary
3. this.bonus
Bukan:
constructor(...) {
this.salary = salary; // ❌
super(...);
}
13. Kenapa super() harus terlebih dahulu?
Karena ketika membuat object Employee, JavaScript/TypeScript perlu memastikan bagian parent (Person) sudah diinisialisasi.
Secara mental model:
new Employee(...)
│
↓
buat bagian Person terlebih dahulu
│
↓
jalankan Person constructor
│
↓
super(...)
│
↓
lanjutkan Employee
│
↓
inisialisasi salary & bonus
Jadi:
super()= panggil constructor parent.
14. Contoh lengkap Employee
Kita gabungkan semuanya:
class Person {
name: string;
dateOfBirth: string;
gender: string;
constructor(
name: string,
dateOfBirth: string,
gender: string
) {
this.name = name;
this.dateOfBirth = dateOfBirth;
this.gender = gender;
}
calculateAge() {
const currentYear = new Date().getFullYear();
const birthYear = new Date(this.dateOfBirth).getFullYear();
return currentYear - birthYear;
}
}
class Employee extends Person {
salary: number;
bonus: number;
constructor(
name: string,
dateOfBirth: string,
gender: string,
salary: number,
bonus: number
) {
super(name, dateOfBirth, gender);
this.salary = salary;
this.bonus = bonus;
}
getSalary() {
return this.salary + this.bonus;
}
}
Sekarang kita membuat object:
const employee = new Employee(
"John",
"1991-08-30",
"Male",
10000,
2000
);
15. Employee sekarang punya apa?
Walaupun class Employee hanya mendeklarasikan:
salary
bonus
getSalary()
object employee juga bisa menggunakan:
employee.name
karena name diwarisi dari Person.
Bisa:
employee.gender
Bisa:
employee.dateOfBirth
Dan yang paling penting:
employee.calculateAge();
Padahal calculateAge() ditulis di Person, bukan di Employee.
Inilah bukti bahwa inheritance bekerja.
16. getSalary() tetap milik Employee
Employee juga memiliki fitur khusus:
getSalary() {
return this.salary + this.bonus;
}
Jadi:
employee.getSalary();
akan menghasilkan:
10000 + 2000
= 12000
Dengan demikian Employee mendapatkan dua jenis fitur:
Dari parent
name
gender
dateOfBirth
calculateAge()
Dari dirinya sendiri
salary
bonus
getSalary()
17. Sekarang Athlete
Kita bisa membuat:
class Athlete extends Person {
country: string;
medals: number;
constructor(
name: string,
dateOfBirth: string,
gender: string,
country: string,
medals: number
) {
super(name, dateOfBirth, gender);
this.country = country;
this.medals = medals;
}
participate() {
// ...
}
}
Sekarang:
Person
│
├── name
├── gender
├── dateOfBirth
└── calculateAge()
│
├───────────────┐
↓ ↓
Employee Athlete
│ │
├ salary ├ country
├ bonus ├ medals
└ getSalary() └ participate()
Ini struktur inheritance.
18. Membuat object Athlete
Misalnya:
const athlete = new Athlete(
"Michael",
"1995-04-10",
"Male",
"Indonesia",
10
);
Athlete sekarang memiliki:
name = Michael
gender = Male
dateOfBirth = 1995-04-10
country = Indonesia
medals = 10
Dan juga memiliki method:
athlete.calculateAge();
yang berasal dari Person.
Serta:
athlete.participate();
yang merupakan method khusus Athlete.
19. Hal menarik: satu parent bisa punya banyak child
Ini salah satu keuntungan besar inheritance.
Kita bisa punya:
Person
│
┌───────────┼───────────┐
↓ ↓ ↓
Employee Athlete Student
Semua bisa mewarisi:
name
gender
dateOfBirth
calculateAge()
Tetapi masing-masing punya fitur sendiri.
Employee
├── salary
├── bonus
└── getSalary()
Athlete
├── country
├── medals
└── participate()
Student
├── school
├── grade
└── study()
Jadi kita membuat kode bersama hanya sekali, di Person.
20. Keuntungan pertama: menghindari code duplication
Tanpa inheritance:
Employee
├── name
├── gender
├── dateOfBirth
└── calculateAge()
Athlete
├── name
├── gender
├── dateOfBirth
└── calculateAge()
Duplikasi.
Dengan inheritance:
Person
├── name
├── gender
├── dateOfBirth
└── calculateAge()
↑
│
┌─────┴─────┐
Employee Athlete
Kode bersama hanya ditulis satu kali.
21. Keuntungan kedua: maintainability
Ini sangat penting.
Bayangkan calculateAge() memiliki bug.
Tanpa inheritance, mungkin kita punya:
Employee.calculateAge()
Athlete.calculateAge()
Student.calculateAge()
Kita harus memperbaiki semuanya.
Dengan inheritance:
Person.calculateAge()
digunakan oleh semuanya.
Kalau kita memperbaiki:
Person.calculateAge()
maka Employee dan Athlete otomatis menggunakan versi yang sudah diperbaiki.
Jadi maintenance lebih mudah.
22. Keuntungan ketiga: kode lebih terorganisasi
Kita bisa menaruh sesuatu berdasarkan tanggung jawabnya.
Hal-hal yang berlaku untuk semua person:
Person
├── name
├── gender
├── dateOfBirth
└── calculateAge()
Hal-hal khusus employee:
Employee
├── salary
├── bonus
└── getSalary()
Hal-hal khusus athlete:
Athlete
├── country
├── medals
└── participate()
Jadi class menjadi lebih rapi.
23. Bedakan extends dan super
Ini sangat penting.
extends
Digunakan untuk membuat hubungan inheritance.
class Employee extends Person {
}
Bacanya:
Employee mewarisi Person.
super()
Digunakan untuk memanggil constructor parent.
constructor(...) {
super(name, dateOfBirth, gender);
}
Bacanya:
Jalankan constructor
Person.
Jadi:
extends
↓
membuat hubungan parent-child
super()
↓
memanggil constructor parent
24. Analogi keluarga
Bayangkan:
MANUSIA
│
┌─────────┴─────────┐
↓ ↓
KARYAWAN ATLET
Semua manusia punya:
nama
jenis kelamin
tanggal lahir
umur
Tapi karyawan punya tambahan:
gaji
bonus
Sedangkan atlet punya:
negara
medali
kompetisi
Tidak masuk akal jika kita menulis ulang:
nama
gender
tanggal lahir
cara menghitung umur
di setiap class.
Lebih masuk akal membuat:
Person
sebagai dasar.
25. Hubungan “is-a”
Ada satu cara yang sangat bagus untuk mengenali kapan inheritance cocok digunakan.
Tanyakan:
Apakah Child “adalah” Parent?
Contoh:
Employee is a Person
✅ masuk akal.
Athlete is a Person
✅ masuk akal.
Tetapi:
Engine is a Car
❌ tidak masuk akal.
Engine bukan car.
Engine adalah bagian dari car.
Ini biasanya mengarah ke konsep composition, bukan inheritance.
Untuk tahap sekarang, cukup ingat:
Inheritance cocok ketika hubungan antar-class adalah hubungan “is-a”.
26. Shorthand property + inheritance
Karena sebelumnya kita sudah belajar shorthand property initialization, constructor Employee sebenarnya bisa dibuat lebih ringkas.
Misalnya:
class Employee extends Person {
constructor(
name: string,
dateOfBirth: string,
gender: string,
public salary: number,
public bonus: number
) {
super(name, dateOfBirth, gender);
}
getSalary() {
return this.salary + this.bonus;
}
}
Di sini:
public salary: number
dan:
public bonus: number
otomatis menjadi property.
Tetapi name, dateOfBirth, dan gender berasal dari parent Person, sehingga kita kirim ke:
super(name, dateOfBirth, gender);
27. Alur ketika new Employee() dijalankan
Ini bagian yang bagus untuk benar-benar memahami inheritance.
Misalnya:
const employee = new Employee(
"John",
"1991-08-30",
"Male",
10000,
2000
);
Yang terjadi secara konsep:
new Employee(...)
│
↓
Employee constructor
│
↓
super(...)
│
↓
Person constructor
│
├── this.name = "John"
├── this.dateOfBirth = "1991-08-30"
└── this.gender = "Male"
│
↓
kembali ke Employee constructor
│
├── this.salary = 10000
└── this.bonus = 2000
│
↓
Employee selesai dibuat
Hasil akhirnya adalah satu object yang mempunyai bagian parent + child.
28. Jangan salah memahami inheritance
Inheritance bukan berarti:
Employee membuat copy-paste kode Person.
Bukan begitu.
Konsepnya lebih seperti:
Employee mendapatkan kemampuan dari Person melalui hubungan inheritance.
Karena itu Employee bisa menggunakan:
employee.calculateAge();
meskipun method tersebut didefinisikan di Person.
29. Ringkasan istilah
| Istilah | Arti |
|---|---|
extends | Membuat class mewarisi class lain |
| Parent class | Class yang diwarisi |
| Base class | Nama lain parent class |
| Superclass | Nama lain parent class |
| Child class | Class yang mewarisi |
| Derived class | Nama lain child class |
| Subclass | Nama lain child class |
super() | Memanggil constructor parent |
30. Ringkasan keseluruhan lecture
Sebelum inheritance:
Person
├── name
├── gender
├── dateOfBirth
└── calculateAge()
Employee
├── name ← duplikasi
├── gender ← duplikasi
├── dateOfBirth
├── calculateAge()
├── salary
├── bonus
└── getSalary()
Athlete
├── name ← duplikasi
├── gender ← duplikasi
├── dateOfBirth
├── calculateAge()
├── country
├── medals
└── participate()
Setelah inheritance:
Person
│
┌────────────┴────────────┐
↓ ↓
Employee Athlete
│ │
┌─────┴─────┐ ┌─────┴──────┐
↓ ↓ ↓ ↓
salary bonus country medals
getSalary() participate()
Dan keduanya otomatis mendapatkan:
name
gender
dateOfBirth
calculateAge()
dari Person.
🧠 Mental model paling penting
Kalau kamu hanya mengingat 4 hal dari lecture ini, ingat ini:
1. extends
class Employee extends Person
Employee mewarisi Person.
2. Parent class
class Person
Berisi property/method yang sama-sama dibutuhkan oleh banyak class.
3. Child class
class Employee extends Person
Berisi fitur tambahan yang spesifik untuk Employee.
4. super()
super(name, dateOfBirth, gender);
Memanggil constructor parent untuk menginisialisasi bagian yang diwarisi.
Jadi pola berpikirnya:
APA YANG SAMA?
↓
Parent class
↓
Person
│
┌──────┴──────┐
↓ ↓
Employee Athlete
↓ ↓
fitur khusus fitur khusus
Inti inheritance adalah: jangan tulis ulang kode yang sama. Taruh kode bersama di parent class, lalu child class mewarisinya menggunakan extends. Dengan begitu kode menjadi lebih DRY (Don’t Repeat Yourself), mudah dirawat, dan lebih terorganisasi.