Khái niệm
Đa hình cho phép nhiều đối tượng khác nhau được xử lý qua cùng một giao diện chung, nhưng mỗi đối tượng lại phản hồi theo cách riêng. Đây là cơ chế quan trọng để viết mã mở rộng tốt và ít phụ thuộc vào kiểu cụ thể.
Ví dụ gọi cùng một hành vi trên nhiều đối tượng
class Cat:
def speak(self):
return "Meo meo"
class Dog:
def speak(self):
return "Gau gau"
for animal in [Cat(), Dog()]:
print(animal.speak())
#include <iostream>
#include <vector>
#include <memory>
using namespace std;
class Animal {
public:
virtual string speak() = 0;
};
class Cat : public Animal {
public:
string speak() override { return "Meo meo"; }
};
class Dog : public Animal {
public:
string speak() override { return "Gau gau"; }
};
int main() {
vector<unique_ptr<Animal>> animals;
animals.push_back(make_unique<Cat>());
animals.push_back(make_unique<Dog>());
for (auto& animal : animals) {
cout << animal->speak() << endl;
}
return 0;
}
interface IAnimal
{
string Speak();
}
class Cat : IAnimal
{
public string Speak() => "Meo meo";
}
class Dog : IAnimal
{
public string Speak() => "Gau gau";
}
foreach (IAnimal animal in new IAnimal[] { new Cat(), new Dog() })
{
Console.WriteLine(animal.Speak());
}
class Cat {
speak() {
return "Meo meo";
}
}
class Dog {
speak() {
return "Gau gau";
}
}
for (const animal of [new Cat(), new Dog()]) {
console.log(animal.speak());
}
interface Animal {
speak(): string;
}
class Cat implements Animal {
speak(): string { return "Meo meo"; }
}
class Dog implements Animal {
speak(): string { return "Gau gau"; }
}
for (const animal of [new Cat(), new Dog()]) {
console.log(animal.speak());
}
Kết luận
Đa hình làm cho mã tổng quát hơn và giảm số lượng rẽ nhánh dựa trên kiểu cụ thể. Khi muốn mô tả rõ hợp đồng hành vi chung, bài tiếp theo là Interface, protocol và trait.
Ghi chú theo ngôn ngữ
Python dùng duck typing: nếu đối tượng có phương thức speak(), nó có thể được dùng như một “animal” mà không cần kế thừa. Không cần khai báo interface hay lớp cha chung.
C++ dùng hàm ảo (virtual) để đạt đa hình ở runtime. Phải dùng con trỏ hoặc tham chiếu đến lớp cha để đa hình hoạt động. Từ khóa override đánh dấu phương thức ghi đè để tránh lỗi.
C# dùng virtual/override giống C++, hoặc implement interface. Khác với C++, tham chiếu kiểu lớp cha trong C# tự động hỗ trợ đa hình mà không cần con trỏ.
JavaScript dùng prototype-based inheritance ngầm đinh. Khi gọi phương thức trên đối tượng, JavaScript tự tra cứu từ prototype chain. class là cú pháp đường (syntactic sugar) bên trên cơ chế prototype.
TypeScript hỗ trợ đa hình qua interface, lớp ảo và implements. Hệ thống kiểu tĩnh giúp đảm bảo tại compile time rằng tất cả phương thức trong interface đều được triển khai.
và trait](/dev/programming/oop/interfaces/).
Bình luận