การสืบทอด (Inheritance) เป็นหลักการสำคัญของ OOP ที่ช่วยให้ Class หนึ่ง (Class ลูก หรือ Subclass) สามารถรับคุณสมบัติ (Properties) และพฤติกรรม (Methods) จาก Class อื่น (Class แม่ หรือ Superclass) มาใช้ซ้ำได้ ซึ่งช่วยลดความซ้ำซ้อนของโค้ด
1. การกำหนด Inheritance ด้วย extends
ในการสืบทอด Class เราใช้คีย์เวิร์ด extends
-
Superclass / Parent Class: Class ที่ถูกสืบทอด
-
Subclass / Child Class: Class ที่ทำการสืบทอด
TypeScript (และ JavaScript) ใช้หลักการ Single Inheritance คือ Class ลูกสามารถสืบทอดจาก Class แม่ได้เพียง Class เดียวเท่านั้น
// Superclass / Parent Class
class Animal {
name: string;
constructor(name: string) {
this.name = name;
}
eat(): void {
console.log(`${this.name} is eating.`);
}
}
// Subclass / Child Class สืบทอดจาก Animal
class Dog extends Animal {
breed: string; // คุณสมบัติใหม่
constructor(name: string, breed: string) {
// ต้องกำหนด constructor ใหม่
super(name); // ต้องเรียก constructor ของ Class แม่
this.breed = breed;
}
bark(): void { // พฤติกรรมใหม่
console.log(`${this.name} is barking.`);
}
}
// การเรียกใช้งาน
const myDog = new Dog("Buddy", "Pug");
myDog.eat(); // เรียกใช้ method ที่สืบทอดมาจาก Animal (Output: Buddy is eating.)
myDog.bark(); // เรียกใช้ method ของ Dog เอง
2. การเรียกใช้ Constructor ของ Class แม่ (super())
เมื่อ Class ลูกมี Constructor ของตัวเอง จะต้องเรียกใช้ super() เป็นคำสั่ง แรก ภายใน Constructor เพื่อส่งผ่าน Argument ที่จำเป็นไปยัง Constructor ของ Class แม่
// (ดูตัวอย่างด้านบน)
class Dog extends Animal {
// ...
constructor(name: string, breed: string) {
// ต้องเรียก super(name) เพื่อให้ Animal constructor กำหนดค่า this.name
super(name);
this.breed = breed;
}
// ...
}
3. การกำหนด Overriding และ super Keyword
Overriding คือการที่ Class ลูกกำหนด Property หรือ Method ที่มีชื่อและ Signature (รูปแบบพารามิเตอร์) เหมือนกับ Class แม่ เพื่อให้มีพฤติกรรมที่แตกต่างไปจากเดิม
A. การใช้ override Keyword (แนะนำใน TS)
TypeScript ในเวอร์ชันใหม่ (ตั้งแต่ 4.3 เป็นต้นไป) รองรับคีย์เวิร์ด override ซึ่งช่วยให้มั่นใจว่า Method นั้นมีอยู่จริงใน Class แม่ หากไม่มีจะแสดง Error (เทียบเท่ากับ @override ใน Dart)
class Animal {
move(distance: number = 0): void {
console.log(`Animal moved ${distance}m.`);
}
}
class Horse extends Animal {
// ใช้ 'override' เพื่อให้ TypeScript ตรวจสอบว่ามี move() ใน Animal จริง
override move(distance: number = 40): void {
// 1. super.move() เรียกใช้ method move() ของ Class แม่
super.move(distance);
// 2. พฤติกรรมที่แตกต่างของ Class ลูก
console.log("Horse galloped!");
}
}
const myHorse = new Horse();
myHorse.move(50);
// Output: Animal moved 50m.
// Output: Horse galloped!
B. การใช้ super ในการเข้าถึง Class แม่
-
super(): ใช้ใน Constructor เพื่อเรียก Constructor ของ Class แม่ -
super.method(): ใช้ใน Method เพื่อเรียก Method ที่ถูก Overridden ของ Class แม่ -
super.property: ใช้เพื่อเข้าถึง Property ของ Class แม่
4. การควบคุมการเข้าถึงใน Inheritance
การใช้ Access Modifiers มีความสำคัญเมื่อทำงานกับการสืบทอด:
| Modifier | Class แม่ | Class ลูก (extends) | ภายนอก |
| public | ✔️ | ✔️ | ✔️ |
| private | ✔️ | ❌ | ❌ |
| protected | ✔️ | ✔️ | ❌ |
protected เป็นตัว Modifier ที่มีความสำคัญที่สุดในการ Inheritance เพราะมันอนุญาตให้ Class ลูกเข้าถึง Property หรือ Method ที่ถูกป้องกันได้ แต่ยังคงซ่อนจากโค้ดภายนอก
class Vehicle {
protected speed: number = 0; // Class ลูกเข้าถึงได้
protected accelerate(amount: number): void {
this.speed += amount;
}
}
class Car extends Vehicle {
public drive(): void {
super.accelerate(50); // Car เข้าถึง protected accelerate ได้
console.log(`Car speed: ${this.speed} km/h`); // Car เข้าถึง protected speed ได้
}
}
const myCar = new Car();
myCar.drive();
// myCar.accelerate(10); // Error: 'accelerate' is protected