Bài 12: TypeScript – Class: Inheritance, OverRiding methods
Ở bài viết trước chúng ta đã tìm hiểu về fields, constructor, ở phần này chúng ta sẽ cùng nhau tìm hiểu tiếp về kế thừa (inheritance), các vấn đề liên quan đến phương thức (method) của class trong TypeScript nhé. Đây là những đặc điểm giúp cho việc sử dụng class linh hoạt hơn và sử dụng chúng rất nhiều trong quá trình làm việc của chúng ta.
Nội dung của bài
Inheritance – Kế thừa
Kế thừa cực kỳ hữu dụng trong việc tái sử dụng code, thể hiện sự đa hình, đa dạng, hữu ích cho việc tối ưu code của chúng ta.
Extends
Để tạo một class con kế thừa từ một class cha, chúng ta sử dụng keyword extends. Cùng xem ví dụ dưới đây
class Person {
name: string;
age: number;
constructor(name: string, age: number) {
this.age = age
this.name = name
}
getName() {
return this.name;
}
}
class Student extends Person {
className: string;
constructor(name:string, age: number, className: string) {
super(name, age)
this.className = className;
}
}
Ở ví dụ trên, class Student kế thừa class Persion, cho nên class Student sẽ có toàn bộ các fields, methods của class Person.
let student = new Student("unclebob", 20, "yeulaptrinh academy");
console.log(student); // Student { age: 20, name: 'unclebob', className: 'yeulaptrinh academy' }
console.log(student.age); // 20
console.log(student.getName()); // unclebob
phương thức super() là cách mà class Student ( class con ) gọi hàm constructor của class Person ( class cha ) và truyền các param vào class cha đó.
Lưu ý:
- super() phải luôn được gọi đầu tiên trong constructor của lớp con
- mỗi một class chỉ được extends một class duy nhất
class Student extends Person {
className: string;
constructor(name:string, age: number, className: string) {
this.className = className; // err: 'super' must be called before accessing 'this' in the constructor of a derived class.
super(name, age)
}
}
Implement
keyword implement được dùng trong trường hợp một class muốn kế thừa một hoặc nhiều interface. Các đối tượng (object) được khởi tạo từ class ấy đều có thể gán các interface kìa làm type cho chính nó
interface IPerson {
name: string;
age: number;
}
interface IEmployee {
position: string;
getCurrentPosition(): string;
}
class Officer implements IEmployee, IPerson {
name: string;
age: number;
position: string;
constructor (name: string, age: number, position: string) {
this.age = age
this.name = name
this.position = position
}
getCurrentPosition (): string {
return this.position
}
}
class Officer đã implements từ 2 interfaces là IEmployee và Iperson. Officer bắt buộc phải có hết toàn bộ các field, các method bên trong của hai interface trên.
Khi khởi tạo object từ class Officer, chúng ta có thể sử dụng IEmployee hoặc IPerson làm type của nó.
let officer = new Officer("unclebob", 24, "BackOfficer")
let developer: IEmployee = new Officer("unclebob", 24, "Developer")
let admin: IPerson = new Officer("unclebob", 24, "Admin")
console.log(officer.name) // Property 'name' does not exist on type 'IEmployee'.
console.log(admin.getCurrentPosition()) // Property 'getCurrentPosition' does not exist on type 'IPerson'
Ở ví dụ trên, chúng ta thấy các object developer, admin mặc dù được khởi tạo từ class Officer nhưng đều có thể có chỉ định type riêng biệt, tuy nhiên chúng không thể có toàn bộ thuộc tính, methods của nhau.
Interface extends Class
Interface có thể kế thừa một class và chứa tất cả các properties của class đó. Các biến sử dụng interface ấy đều bắt buộc phải có đầy đủ tất các properties
class Person {
name: string;
age: number;
constructor(name: string, age: number) {
this.age = age
this.name = name
}
}
interface IEmployee extends Person{
position: string;
}
let developer: IEmployee = {position: 'developer', name: 'uncleBob', age: 24}
let employee: IEmployee = {position: 'officer'}
// Type '{ position: string; }' is missing the following properties from type 'IEmployee': name, age
Methods – Overriding method
Method là phương thức ở trong class, nó có vai trò quan trọng không kém field hay constructor.
Một class con có thể định nghĩa, khai báo lại một phương thức (methods) từ class cha, quá trình đó gọi là overriding method. Quá trình này được sử dụng rất nhiều trong phát triển phần mềm, thể hiện sự linh hoạt trong việc sử dụng code của chúng ta.
class Vehicle {
name: string;
constructor(name: string) {
this.name = name
}
getPrice (price: number) {
return `${this.name}'s price is ${price} dollards`
}
}
class Motor extends Vehicle {
price: number;
constructor(name: string, price: number) {
super(name)
this.price = price
}
getPrice () {
return super.getPrice(this.price)
}
}
class Bike extends Vehicle {
constructor(name: string) {
super(name)
}
getPrice (price: number) {
return `${this.name} worths ${price} dollards`
}
}
let motorBike = new Motor("Motor Bike", 1000)
let bike = new Bike("Bicycle")
console.log(motorBike.getPrice()) // Motor Bike's price is 1000 dollards
console.log(bike.getPrice(500)) // Bicycle worths 500 dollards
Một method khi override lại từ method cha thì cần có đúng kiểu tên và kiểu trả về như method cha. Keyword super sẽ giúp tiếp cận tới các thuộc tính và phương thức của class cha từ class con.
Summary
Bài viết này chúng ta đã đi qua về các khái niệm cơ bản của kế thừa, overriding methods, cách làm việc với class, với interface.. Hi vọng bài viết này giúp ích bạn trong quá trình làm việc, rất mong nhận được sự đóng góp của các bạn để chúng mình hoàn thiện bài viết hơn.