TypeScript - Thừa kế (Inheritance)

Xin chào các nhà lập trình tương lai! Hôm nay, chúng ta sẽ bắt đầu một hành trình thú vị vào thế giới thừa kế của TypeScript. Là người giáo viên máy tính gần gũi của bạn, tôi ở đây để hướng dẫn bạn qua chủ đề fascinating này. Vậy, hãy lấy cặp背包 ảo của bạn, và cùng nhau lặn vào!

TypeScript - Inheritance

Thừa kế là gì?

Trước khi chúng ta bắt đầu, hãy hiểu xem thừa kế thực sự có nghĩa là gì. Hãy tưởng tượng bạn đang tạo một cây gia đình. Mỗi thế hệ mới kế thừa một số đặc điểm từ cha mẹ của họ. Trong lập trình, thừa kế hoạt động tương tự. Nó cho phép một lớp mới được dựa trên một lớp đã.exists, kế thừa các thuộc tính và phương thức của nó. Đúng là cool, phải không?

Thừa kế lớp đơn (Single Class Inheritance)

Hãy bắt đầu với hình thức đơn giản nhất của thừa kế: thừa kế lớp đơn. Đây là khi một lớp (lớp con) kế thừa từ một lớp khác (lớp cha).

Ví dụ cơ bản

class Animal {
name: string;

constructor(name: string) {
this.name = name;
}

makeSound(): void {
console.log("Some generic animal sound");
}
}

class Dog extends Animal {
breed: string;

constructor(name: string, breed: string) {
super(name);
this.breed = breed;
}

makeSound(): void {
console.log("Woof! Woof!");
}
}

let myDog = new Dog("Buddy", "Golden Retriever");
console.log(myDog.name);  // Output: Buddy
console.log(myDog.breed); // Output: Golden Retriever
myDog.makeSound();        // Output: Woof! Woof!

Trong ví dụ này, Dog đang kế thừa từ Animal. Từ khóa extends được sử dụng để tạo một lớp là con của một lớp khác.

Giải thích

  1. Chúng ta định nghĩa một lớp cơ sở Animal với thuộc tính name và phương thức makeSound.
  2. Sau đó, chúng ta tạo một lớp Dog kế thừa Animal.
  3. Lớp Dog có thuộc tính breed riêng của nó.
  4. Chúng ta sử dụng từ khóa super trong constructor của Dog để gọi constructor của Animal.
  5. Chúng ta ghi đè phương thức makeSound trong lớp Dog.

Từ khóa Super

Bạn có thể đã nhận thấy từ khóa super trong ví dụ trước. Hãy cùng tìm hiểu sâu hơn về điều nó làm.

Ví dụ với Super

class Vehicle {
make: string;
model: string;

constructor(make: string, model: string) {
this.make = make;
this.model = model;
}

getInfo(): string {
return `${this.make} ${this.model}`;
}
}

class Car extends Vehicle {
numDoors: number;

constructor(make: string, model: string, numDoors: number) {
super(make, model);
this.numDoors = numDoors;
}

getInfo(): string {
return `${super.getInfo()} with ${this.numDoors} doors`;
}
}

let myCar = new Car("Toyota", "Corolla", 4);
console.log(myCar.getInfo()); // Output: Toyota Corolla with 4 doors

Giải thích

  1. Từ khóa super được sử dụng trong constructor của Car để gọi constructor của Vehicle.
  2. Trong phương thức getInfo của Car, chúng ta sử dụng super.getInfo() để gọi phương thức getInfo của lớp cha.

Từ khóa super cho phép chúng ta truy cập và gọi hàm trên đối tượng của lớp cha.

Ghi đè phương thức (Method Overriding)

Ghi đè phương thức xảy ra khi một lớp con cung cấp một thực hiện cụ thể cho một phương thức đã được định nghĩa trong lớp cha. Chúng ta thực sự đã thấy điều này trong cả hai ví dụ trước của chúng ta!

Ví dụ khác về Ghi đè phương thức

class Shape {
getArea(): number {
return 0;
}
}

class Circle extends Shape {
radius: number;

constructor(radius: number) {
super();
this.radius = radius;
}

getArea(): number {
return Math.PI * this.radius * this.radius;
}
}

class Rectangle extends Shape {
width: number;
height: number;

constructor(width: number, height: number) {
super();
this.width = width;
this.height = height;
}

getArea(): number {
return this.width * this.height;
}
}

let myCircle = new Circle(5);
console.log(myCircle.getArea()); // Output: 78.53981633974483

let myRectangle = new Rectangle(4, 5);
console.log(myRectangle.getArea()); // Output: 20

Giải thích

  1. Chúng ta có một lớp cơ sở Shape với phương thức getArea trả về 0.
  2. Cả hai lớp CircleRectangle kế thừa Shape và ghi đè phương thức getArea với các thực hiện riêng của chúng.
  3. Lớp Circle tính toán diện tích bằng công thức πr².
  4. Lớp Rectangle tính toán diện tích bằng cách nhân rộng và cao.

Thừa kế đa cấp (Multilevel Inheritance)

Thừa kế đa cấp liên quan đến việc một lớp con kế thừa từ một lớp con khác. Nó giống như một cây gia đình với nhiều thế hệ.

Ví dụ về Thừa kế đa cấp

class Grandparent {
surname: string;

constructor(surname: string) {
this.surname = surname;
}

getSurname(): string {
return this.surname;
}
}

class Parent extends Grandparent {
firstName: string;

constructor(firstName: string, surname: string) {
super(surname);
this.firstName = firstName;
}

getFullName(): string {
return `${this.firstName} ${this.getSurname()}`;
}
}

class Child extends Parent {
middleName: string;

constructor(firstName: string, middleName: string, surname: string) {
super(firstName, surname);
this.middleName = middleName;
}

getFullName(): string {
return `${this.firstName} ${this.middleName} ${this.getSurname()}`;
}
}

let myChild = new Child("John", "Doe", "Smith");
console.log(myChild.getFullName()); // Output: John Doe Smith

Giải thích

  1. Chúng ta có một lớp Grandparent với thuộc tính surname.
  2. Lớp Parent kế thừa Grandparent và thêm thuộc tính firstName.
  3. Lớp Child kế thừa Parent và thêm thuộc tính middleName.
  4. Mỗi lớp có phương thức getFullName riêng của mình.

Tóm tắt các phương thức Thừa kế

Dưới đây là bảng tóm tắt các phương thức và từ khóa chúng ta đã thảo luận:

Phương thức/Từ khóa Mô tả
extends Sử dụng để tạo một lớp là con của một lớp khác
super() Gọi constructor của lớp cha
super.method() Gọi một phương thức từ lớp cha
Ghi đè phương thức Cung cấp một thực hiện cụ thể cho một phương thức trong lớp con

Và thế là xong! Chúng ta đã bao gồm các nguyên tắc cơ bản của thừa kế trong TypeScript. Nhớ rằng, thực hành là cách tốt nhất để hoàn thiện, vì vậy đừng ngần ngại thử nghiệm với các khái niệm này. Chúc các bạn may mắn, những phù thủy TypeScript tương lai!

Credits: Image by storyset