Tính đa hình

Frontend SELF VI
Mức độ , Bài học
Có sẵn

10.1 Cơ bản về tính đa hình

Tính đa hình là một trong những khái niệm then chốt của lập trình hướng đối tượng (OOP). Nói chung, tính đa hình cho phép các đối tượng của các lớp khác nhau xử lý dữ liệu bằng cách sử dụng cùng một interface. Trong ngữ cảnh của JavaScript, điều này có nghĩa là các đối tượng khác nhau có thể có các phương thức cùng tên và các phương thức này có thể được gọi trên các đối tượng mà không cần biết kiểu cụ thể của chúng.

Các loại đa hình

Trong JavaScript, các loại đa hình chính là:

1. Ad-hoc đa hình (ad-hoc polymorphism):

  • Đa hình phương thức, gọi các phương thức cùng tên cho các đối tượng kiểu khác nhau
  • Các ví dụ bao gồm quá tải hàm và toán tử (mặc dù không được hỗ trợ trực tiếp trong JavaScript, nhưng có thể được mô phỏng)

2. Đa hình kiểu phụ (Subtype polymorphism):

  • Đa hình kiểu phụ hoặc bao gồm, khi các đối tượng của các lớp khác nhau, kế thừa từ lớp cơ sở cùng, có thể được xử lý như các đối tượng của lớp cơ sở
  • Đây là loại đa hình chính, được thực hiện thông qua kế thừa và các interface

Lợi ích của tính đa hình:

  1. Đơn giản hóa code: tính đa hình cho phép viết code linh hoạt và tổng quát hơn, có thể hoạt động với các loại đối tượng khác nhau mà không cần biết loại cụ thể của chúng.
  2. Mở rộng: tính đa hình dễ dàng thêm các loại mới và hành vi vào hệ thống mà không cần thay đổi code hiện có.
  3. Hỗ trợ: tính đa hình thúc đẩy phân chia trách nhiệm rõ ràng hơn và tăng khả năng đọc và bảo trì của code.

10.2 Ví dụ về tính đa hình trong JavaScript

Đa hình kiểu phụ thông qua kế thừa

Ví dụ 1: Xử lý các loại đối tượng khác nhau bằng một interface

Trong ví dụ này, hàm playWithAnimal nhận một đối tượng kiểu Animal và gọi phương thức makeSound. Các đối tượng DogCat, kế thừa từ Animal, ghi đè phương thức makeSound, và khi gọi phương thức trên mỗi đối tượng nhận được kết quả khác nhau.

JavaScript
    
      class Animal {
        makeSound() {
          console.log('Some generic sound');
        }
      }

      class Dog extends Animal {
        makeSound() {
          console.log('Woof!');
        }
      }

      class Cat extends Animal {
        makeSound() {
          console.log('Meow!');
        }
      }

      function playWithAnimal(animal) {
        animal.makeSound();
      }

      const dog = new Dog();
      const cat = new Cat();

      playWithAnimal(dog); // Sẽ in ra: Woof!
      playWithAnimal(cat); // Sẽ in ra: Meow!
    
  

10.3 Đa hình qua interface (Duck Typing)

Trong JavaScript không có hỗ trợ tích hợp cho các interface, như trong các ngôn ngữ khác, như TypeScript hay Java. Thay vào đó sử dụng cách tiếp cận gọi là "kiểu gõ vịt" (Duck Typing). Điều này có nghĩa là đối tượng được coi là phù hợp với interface nếu nó có các phương thức và thuộc tính cần thiết, bất kể loại cụ thể của nó hay khuôn mẫu.

Quan trọng!

Quy tắc vịt (duck): nếu cái gì đó trông giống vịt, bơi như vịt và quạ như vịt, thì nó có thể là vịt thực sự.

Ví dụ 2: Sử dụng kiểu gõ vịt

Trong ví dụ này, hàm takeOff nhận bất kỳ đối tượng nào có phương thức fly. Các đối tượng BirdAirplane hiện thực phương thức fly, do đó chúng có thể được truyền vào takeOff.

JavaScript
    
      class Bird {
        fly() {
          console.log('Flying...');
        }
      }

      class Airplane {
        fly() {
          console.log('Jet engine roaring...');
        }
      }

      function takeOff(flyingObject) {
        flyingObject.fly();
      }

      const bird = new Bird();
      const airplane = new Airplane();

      takeOff(bird);      // Sẽ in ra: Flying...
      takeOff(airplane);  // Sẽ in ra: Jet engine roaring...
    
  

10.4 Đa hình qua hàm

Trong JavaScript, hàm là các đối tượng bậc nhất, và chúng có thể được truyền và sử dụng để thực hiện hành vi đa hình.

Ví dụ 3: Đa hình qua hàm

Trong ví dụ này, hàm greet nhận một hàm khác làm tham số và gọi nó. Điều này cho phép sử dụng các hàm khác nhau để thực hiện các hành động khác nhau.

JavaScript
    
      function greetMorning() {
        console.log('Good morning!');
      }

      function greetEvening() {
        console.log('Good evening!');
      }

      function greet(greetingFunction) {
        greetingFunction();
      }

      greet(greetMorning); // Sẽ in ra: Good morning!
      greet(greetEvening); // Sẽ in ra: Good evening!
    
  

10.5 Đa hình qua quá tải phương thức (Mô phỏng)

JavaScript không hỗ trợ trực tiếp quá tải phương thức, như một số ngôn ngữ lập trình khác. Tuy nhiên, có thể mô phỏng quá tải phương thức bằng cách sử dụng các tham số hàm và kiểm tra kiểu của chúng.

Ví dụ 4: Mô phỏng quá tải phương thức

Trong ví dụ này, phương thức add nhận hai tham số và thực hiện các hành động khác nhau dựa trên các kiểu của chúng. Nếu các tham số là số, phương thức sẽ cộng chúng. Nếu các tham số là mảng, phương thức sẽ nối chúng.

JavaScript
    
      class Calculator {
        add(a, b) {
          if (typeof a === 'number' && typeof b === 'number') {
            return a + b;
          } else if (Array.isArray(a) && Array.isArray(b)) {
            return a.concat(b);
          } else {
            throw new Error('Invalid arguments');
          }
        }
      }

      const calc = new Calculator();
      console.log(calc.add(1, 2));           // Sẽ in ra: 3
      console.log(calc.add([1, 2], [3, 4])); // Sẽ in ra: [1, 2, 3, 4]
    
  
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION