THÔNG DỤNG
OOP
ES6
ES(X)
CÁC CHỦ ĐỀ
BÀI MỚI NHẤT
MỚI CẬP NHẬT

Extends trong Javascript - kế thừa và ghi đè phương thức

Trong bài này chúng ta sẽ tìm hiểu cách sử dụng từ khóa extends trong Javascript, qua đó sẽ giúp bạn hiểu được tính kế thừa và cách ghi đè phương thức trong js.

test php

banquyen png
Bài viết này được đăng tại freetuts.net, không được copy dưới mọi hình thức.

Kể từ ES6 thì javascript đã trở thành một ngôn ngữ siêu khó, ta có thể tạo đối tượng bằng nhiều cách khác nhau như function và class. Và với sự ra đời của class thì chúng ta có thêm các khái niệm về tính kế thừa (inheritance) và ghi đè phương thức (overriding).

1. Extends trong Javascript là gì?

Trong javascript, extends là một từ khóa dùng để khai báo một lớp được kế thừa từ một lớp khác. Qua đó lớp kế thừa có thể sử dụng những phương thức và thuộc tính của lớp được kế thừa.

Nếu lớp A kế thừa từ lớp B thì lớp A ta gọi là lớp con, còn lớp B ta gọi là lớp cha.

Bài viết này được đăng tại [free tuts .net]

Câu hỏi được đặt ra là tại sao cần tính kế thừa? Câu trả lời như sau:

Thực tế thì nhiều đối tượng có thể có những thuộc tính và hành động giống nhau, và bắt buộc mỗi đối tượng chúng ta phải cài đặt một class riêng lẻ, thì việc kế thừa sẽ giúp cho việc cài đặt các đối tượng trở nên đơn giản hơn.

Ví dụ: Ta có đối tượng động vật, trong động vật lại có nhiều loại động vật khác nhau như sư tử, rùa.

  • Động vật sẽ có các đặc tính như: Số cân, màu lông, chủng loại...
  • Động vật sẽ có các hành động như: Ăn, chạy, săn mồi ...

Những đặc tính và hành động trên cũng có trong hai đối tượng sư tửrùa, vì vậy hai đối tượng này ta sẽ khai báo kế thừa đối tượng động vật.

2. Xây dựng class extends trong javascript

Bây giờ ta sẽ xây dựng ba class như ví dụ mà mình đã nói ở phần 1, bằng cách sử dụng từ khóa extends trong js.

Khai báo lớp Animal.

class Animal {
    constructor(name) {
        this.name = name;
        this.speed = 0; // Tốc độ chạy 0km / h
    }
    run(speed) {
        this.speed = speed;
        alert(`${this.name} chạy tốc độ là ${this.speed}.`);
    }
    stop() {
        this.speed = 0;
        alert(`${this.name} đứng yên.`);
    }
}

Khai báo lớp Lion kế thừa từ lớp Animal: Lion có một đặc tính riêng biệt mà động vật khác không có, đó là Gầm. Vì vậy ngoài các hành động runstop thì mình sẽ khai báo thêm hành động roar.

class Lion extends Animal{
    roar(){
        alert(`${this.name} đang gầm`);
    }
}

let lion = new Lion("Sử tử");
lion.run(80);
lion.stop();
lion.roar();

Khai báo lớp con thỏ kế thừa từ lớp Animal: Con thỏ là một động vật nhỏ bé nên nó hay bị các động vật khác tấn công, vì vậy nó có thêm hành động ẩn nấp.

class Rabbit extends Animal {
  hide() {
    alert(`${this.name} đang ẩn nấp`);
  }
}

let rabbit = new Rabbit("Con thỏ");
rabbit.run(0.05);
rabbit.stop();
rabbit.hide();

Như vậy lớp con sẽ có đầy đủ những phương thức và thuộc tính của lớp cha, đây là một quy tắc hiển nhiên trong việc phân cấp cha con.

Có một vấn đề rất quan trọng trong việc kế thừa, đó là mức độ truy cập đến các thuộc tính và phương thức trong lớp. Vấn đề này mình sẽ trình bày trong bài viết private và protected trong js.

3. Overriding trong Javascript

Overriding là kỹ thuật ghi đè hàm (viết lại phương thức) của lớp cha.

Đôi khi những hành động bên trong lớp cha sẽ không thích ứng với các lớp con, lúc này lớp con có thể ghi đè lại các phương thức của lớp cha thông qua kỹ thuật Overriding.

Ví dụ với lớp con thỏ dưới đây, hành động chạy (run) của nó thường sẽ đi kèm với hành động ẩn nấp (hide). Vì vậy ta có thể viết lại hàm run trong lớp Rabbit như sau:

class Animal {
    constructor(name) {
        this.name = name;
    }
    run() {
        console.log(`${this.name} đang chạy`);
    }
}

class Rabbit extends Animal {
    // Override hàm run
    run(){
        super.run();
        this.hide();
    }
    hide() {
        console.log(`${this.name} đang ẩn nấp`);
    }
}

let rabbit = new Rabbit("Con thỏ");
rabbit.run();

Tòm lại:

  • Trong ví dụ này thì phương thức hide đã bị ghi đè lại vì nó được khai báo ngay trong lớp con.
  • Để gọi đến hàm run ở lớp cha thì ta phải sử dụng từ khóa super, nếu không nó sẽ hiểu là bạn đang gọi đếm hàm run ở lớp con.

4. Overriding constructor javascript

Nếu bạn muốn overriding hàm khởi tạo constructor thì cần chú ý một số vấn đề như sau.

  • Nếu bạn không muốn override hàm constructor thì không phải làm gì cả.
  • Nếu bạn tạo một hàm constructor ở hàm con thì bắt buộc phải sử dụng từ khóa super để gọi đến hàm constructor của lớp cha, và phải đặt vị trí đầu tiên.

Trường hợp này là ok.

class Animal {
    constructor(name) {
        console.log('Hàm khởi tạo lớp cha');
    }
}

class Rabbit extends Animal {

}

let rabbit = new Rabbit();

Trường hợp dưới đây là sai, bởi vì bạn đã tạo một constructor ở lớp con, nên bắt buộc phải sử dụng từ khóa super.

class Animal {
    constructor(name) {
        console.log('Hàm khởi tạo lớp cha');
    }
}

class Rabbit extends Animal {
    constructor(name, age) {
        console.log('Hàm khởi tạo lớp con');
    }
}

Sửa lại như sau:

class Animal {
    constructor(name) {
        console.log('Hàm khởi tạo lớp cha');
    }
}

class Rabbit extends Animal {
    constructor(name, age) {
        super(name);
        console.log('Hàm khởi tạo lớp con');
    }
}

let rabbit = new Rabbit();

Mặc dù hàm cha không có hàm constructor nhưng bạn cũng phải sử dụng từ khóa supper.

class Animal {
}

class Rabbit extends Animal {
    constructor() {
        super();
        console.log('Hàm khởi tạo lớp con');
    }
}

let rabbit = new Rabbit();

Như vậy là mình đã giới thiệu xong từ khóa extends trong javascript, cũng như cách sử dụng nó để tạo ra những lớp kế thừa. Bài này mình xin dừng ở đây, hẹn gặp lại các bạn ở bài tiếp theo.

Cùng chuyên mục:

Functional Programming là gì? Tại sao và khi nào bạn nên sử dụng trong JavaScript

Functional Programming là gì? Tại sao và khi nào bạn nên sử dụng trong JavaScript

Những tính năng mới trong ES6+ trong JavaScript

Những tính năng mới trong ES6+ trong JavaScript

4 cách tránh memory leaks trong JavaScript

4 cách tránh memory leaks trong JavaScript

Capturing và bubbling Event trong Javascript

Capturing và bubbling Event trong Javascript

Phân biệt prototype và __proto__ trong JavaScript

Phân biệt prototype và __proto__ trong JavaScript

Cách hoạt động của Event Loop trong JavaScript

Cách hoạt động của Event Loop trong JavaScript

Phương thức bind(), call(), và apply() trong JavaScript

Phương thức bind(), call(), và apply() trong JavaScript

Cách khắc phục lỗi

Cách khắc phục lỗi "hoisting" trong JavaScript

Sử dụng Promise.all và Promise.race để quản lý các Promise trong JavaScript

Sử dụng Promise.all và Promise.race để quản lý các Promise trong JavaScript

Xử lý bất đồng bộ bằng vòng lặp for-await trong JavaScript

Xử lý bất đồng bộ bằng vòng lặp for-await trong JavaScript

Sự khác biệt giữa Promise, Callback và Async/Await trong JavaScript

Sự khác biệt giữa Promise, Callback và Async/Await trong JavaScript

Cách sử dụng Async functions trong JavaScript

Cách sử dụng Async functions trong JavaScript

Hàm String isspace() trong Python

Hàm String isspace() trong Python

Cách tạo số ngẫu nhiên trong Javascript

Cách tạo số ngẫu nhiên trong Javascript

Hướng dẫn cách tạo một số ngẫu nhiên ...

Cách gộp hai object javascript lại với nhau

Cách gộp hai object javascript lại với nhau

Cách lấy chiều dài của object trong Javascript

Cách lấy chiều dài của object trong Javascript

Hướng dẫn giải phương trình bậc 1 bằng Javascript

Hướng dẫn giải phương trình bậc 1 bằng Javascript

Cách dùng nextSibling trong javascript

Cách dùng nextSibling trong javascript

Cách dùng insertAdjacentHTML trong javascript

Cách dùng insertAdjacentHTML trong javascript

Cách dùng innerHTML trong Javascript

Cách dùng innerHTML trong Javascript

Top