JavaScript - Thừa kế (Inheritance)

Xin chào các pháp sư JavaScript tương lai! Hôm nay, chúng ta sẽ bắt đầu một chuyến hành trình đầy thú vị qua thế giới ma thuật của thừa kế trong JavaScript. Đừng lo lắng nếu bạn mới bắt đầu học lập trình; tôi sẽ là người hướng dẫn thân thiện của bạn, và chúng ta sẽ cùng khám phá khái niệm này từng bước một. Vậy, hãy lấy键盘 của bạn (như pháp thuật) và cùng nhau lặn vào!

JavaScript - Inheritance

Thừa kế trong JavaScript

Thừa kế giống như việc truyền lại các đặc điểm gia đình, nhưng trong thế giới lập trình. Hãy tưởng tượng bạn đang tạo một cây gia đình của các đối tượng, nơi mà con cái có thể kế thừa các thuộc tính và phương thức từ cha mẹ. Đúng là rất thú vị phải không?

Hãy bắt đầu với một ví dụ đơn giản:

class Animal {
constructor(name) {
this.name = name;
}

speak() {
console.log(`${this.name} phát ra tiếng động.`);
}
}

class Dog extends Animal {
bark() {
console.log(`${this.name} sủa: Woof woof!`);
}
}

const myDog = new Dog("Buddy");
myDog.speak(); // Output: Buddy phát ra tiếng động.
myDog.bark();  // Output: Buddy sủa: Woof woof!

Trong ví dụ này, Dog kế thừa từ Animal. Điều này có nghĩa là Dog nhận được tất cả các thuộc tính và phương thức của Animal, cộng thêm phương thức riêng của nó bark(). Nó giống như Buddy kế thừa khả năng nói từ tất cả các loài động vật, nhưng cũng có siêu năng lực sủa của riêng mình!

Thừa kế đơn lớp trong JavaScript

Thừa kế đơn lớp là khi một lớp kế thừa từ chỉ một lớp cha. Nó giống như có một người cha siêu cool mà bạn muốn học mọi thứ từ họ.

Dưới đây là một ví dụ khác:

class Vehicle {
constructor(brand) {
this.brand = brand;
}

start() {
console.log(`Khởi động ${this.brand}.`);
}
}

class Car extends Vehicle {
honk() {
console.log(`${this.brand} xe chạy beep beep!`);
}
}

const myCar = new Car("Toyota");
myCar.start(); // Output: Khởi động Toyota.
myCar.honk();  // Output: Toyota xe chạy beep beep!

Ở đây, Car kế thừa từ Vehicle. Nó giống như xe của bạn học cách khởi động từ khái niệm chung về phương tiện, nhưng cũng biết cách bíp vì, à, nó là một chiếc xe!

Từ khóa super() trong JavaScript

Bây giờ, hãy nói về từ khóa super(). Nó giống như một cái gật đầu tôn trọng từ bạn với cha mẹ, công nhận sự đóng góp của họ vào sự tuyệt vời của bạn.

class Animal {
constructor(name) {
this.name = name;
}
}

class Dog extends Animal {
constructor(name, breed) {
super(name); // Gọi constructor của lớp cha
this.breed = breed;
}

introduce() {
console.log(`Tôi là ${this.name}, một con chó ${this.breed}.`);
}
}

const myDog = new Dog("Max", "Labrador");
myDog.introduce(); // Output: Tôi là Max, một con chó Labrador.

Gọi super(name) trong constructor của Dog giống như nói, "Hey cha mẹ Animal, bạn có thể xử lý việc đặt tên cho tôi không?" Nó là cách tái sử dụng logic constructor của lớp cha.

Thừa kế đa cấp trong JavaScript

Thừa kế đa cấp là như một cây gia đình với nhiều thế hệ. Hãy xem một ví dụ:

class Animal {
constructor(name) {
this.name = name;
}

eat() {
console.log(`${this.name} đang ăn.`);
}
}

class Dog extends Animal {
bark() {
console.log(`${this.name} nói woof!`);
}
}

class Labrador extends Dog {
swim() {
console.log(`${this.name} đang bơi.`);
}
}

const myDog = new Labrador("Charlie");
myDog.eat();  // Output: Charlie đang ăn.
myDog.bark(); // Output: Charlie nói woof!
myDog.swim(); // Output: Charlie đang bơi.

Ở đây, Labrador kế thừa từ Dog, mà Dog lại kế thừa từ Animal. Nó giống như Charlie the Labrador học cách ăn từ tất cả các loài động vật, học cách sủa từ chó, và có khả năng bơi đặc biệt của riêng mình.

Thừa kế Hierarchical trong JavaScript

Thừa kế Hierarchical là khi nhiều lớp kế thừa từ một lớp cha duy nhất. Nó giống như anh chị em kế thừa các đặc điểm từ cùng một người cha.

class Vehicle {
constructor(brand) {
this.brand = brand;
}

start() {
console.log(`Khởi động ${this.brand}.`);
}
}

class Car extends Vehicle {
drive() {
console.log(`Lái ${this.brand} xe.`);
}
}

class Motorcycle extends Vehicle {
wheelie() {
console.log(`Làm wheelie trên ${this.brand} mô tô!`);
}
}

const myCar = new Car("Toyota");
const myBike = new Motorcycle("Harley");

myCar.start();    // Output: Khởi động Toyota.
myCar.drive();    // Output: Lái Toyota xe.

myBike.start();   // Output: Khởi động Harley.
myBike.wheelie(); // Output: Làm wheelie trên Harley mô tô!

Cả CarMotorcycle đều kế thừa từ Vehicle, nhưng chúng có các phương thức riêng.

Kế thừa các thành viên tĩnh của lớp

Các thành viên tĩnh thuộc về lớp chứ không phải các thể hiện. Nhưng chúng vẫn có thể được kế thừa! Hãy xem như thế nào:

class MathOperations {
static PI = 3.14159;

static calculateCircleArea(radius) {
return this.PI * radius * radius;
}
}

class AdvancedMath extends MathOperations {
static calculateSphereVolume(radius) {
return (4/3) * this.PI * radius * radius * radius;
}
}

console.log(AdvancedMath.PI); // Output: 3.14159
console.log(AdvancedMath.calculateCircleArea(5)); // Output: 78.53975
console.log(AdvancedMath.calculateSphereVolume(3)); // Output: 113.09733

Ở đây, AdvancedMath kế thừa thuộc tính tĩnh PI và phương thức calculateCircleArea từ MathOperations.

Thừa kế dựa trên prototype trong JavaScript

Trước khi có các lớp ES6, JavaScript sử dụng thừa kế dựa trên prototype. Nó phức tạp hơn một chút, nhưng vẫn rất quan trọng để hiểu:

function Animal(name) {
this.name = name;
}

Animal.prototype.speak = function() {
console.log(`${this.name} phát ra tiếng động.`);
};

function Dog(name) {
Animal.call(this, name);
}

Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;

Dog.prototype.bark = function() {
console.log(`${this.name} sủa: Woof woof!`);
};

const myDog = new Dog("Rex");
myDog.speak(); // Output: Rex phát ra tiếng động.
myDog.bark();  // Output: Rex sủa: Woof woof!

Điều này đạt được cùng kết quả như ví dụ lớp đầu tiên, nhưng sử dụng cú pháp prototype cũ.

Lợi ích của thừa kế

Thừa kế trong JavaScript mang lại nhiều lợi ích:

  1. Tái sử dụng mã
  2. Mở rộng
  3. Dễ bảo trì
  4. Đa hình

Dưới đây là bảng tóm tắt các lợi ích này:

Lợi ích Mô tả
Tái sử dụng mã Kế thừa các thuộc tính và phương thức từ lớp cha, giảm sự trùng lặp
Mở rộng Dễ dàng thêm các tính năng mới vào các lớp hiện có
Dễ bảo trì Thay đổi trong lớp cha tự động phản ánh trong các lớp con
Đa hình Sử dụng các đối tượng của các lớp khác nhau thông qua cùng một giao diện

Nhớ rằng, với quyền lực lớn đi kèm với trách nhiệm lớn. Sử dụng thừa kế một cách khôn ngoan, và mã của bạn sẽ cảm ơn bạn!

Và thế là xong, các bạn! Chúng ta đã cùng nhau hành trình qua vùng đất thừa kế của JavaScript. Tôi hy vọng hướng dẫn này đã chiếu sáng con đường cho bạn. Hãy tiếp tục thực hành, luôn tò mò và chúc bạn lập trình vui vẻ!

Credits: Image by storyset