Đa hình là tính chất quan trọng nhưng khó hiểu nhất của OOP – nắm bắt được tính chất này, bạn sẽ dễ dàng hiểu được tất cả những gì còn lại, kể cả tính trừu tượng sau này. Trong bài này tôi sẽ giải thích nó theo cách đơn giản nhất, sau đó trong phần 2 ta sẽ đào sâu vào, xem những gì thực sự xảy ra ở bên dưới.
Giải thích đơn giản thì đa hình cho phép tự động gọi một phương thức dựa trên các tham số truyền vào (1) hoặc kiểu thực sự của đối tượng bạn đang có (2). (1) Nếu bạn có 2 phương thức:
function Add(x, y : Integer) : Integer;
begin
Add := x + y
end;
function Add(s, t : String) : String;
begin
Add := Concat(s, t)
end;
Vậy nhìn vào các câu lệnh sau bạn hoàn toàn xác định được hàm nào sẽ được gọi:
begin
Writeln(Add(1, 2)); (* Prints "3" *)
Writeln(Add('Hello, ', 'Mammals!')); (* Prints "Hello, Mammals!" *)
end.
Bởi ngay khi dịch, trình biên dịch đã biết chính xác hàm nào được gọi nên người ta còn gọi nó là đa hình tĩnh, các câu lệnh gọi hàm sẽ được sinh ra và gọi trực tiếp đến hàm được chọn. Câu lệnh Writeln(Add(1, 2)); chắc chắn sẽ gọi đến Add(x, y : Integer).
(2) Nếu bạn có chương trình animal (ta sẽ còn dùng tới chương trình trong phần sau) với 2 lớp Dog và Fish thừa kế từ Animal như sau:
class Animal
{
public:
virtual void move() { // đừng quên từ khóa virtual nhé
cout << "Moving";
}
};
class Dog: public Animal
{
public:
void move(){
cout << "Running";
}
};
class Fish: public Animal
{
public:
void move(){
cout << "Swimming";
}
};
Sau đó trong chương trình chính bạn gọi:
Animal *a;
a = &dog;
a->move();
Cho dù a có kiểu trỏ đến Animal, nhưng phương thức được gọi sẽ là Dog::move, chứ không phải Animal::move.
Vẫn biến a đó, bạn lại trỏ đến Fish:
a = &fish;
a->move();
Giờ hàm được gọi sẽ là Fish::move.
Vào thời điểm biên dịch, không ai biết chính xác a có thể trỏ đến kiểu gì, bạn thử nghĩ nếu ta gán a = &fish hoặc a = &dog dựa trên yêu cầu của người dùng thì ta đâu thể biết khi chạy người ta sẽ chọn fish hay dog. Thậm chí a có thể sẽ trỏ đến một đối tượng có kiểu Bird, vốn sẽ chỉ được viết sau này khi chương trình animal đã được dịch và chạy trên máy chủ.
Windows có thể điều khiển được các loại máy in khác nhau cũng nhờ tính đa hình này, thậm chí với một driver thích hợp nó có thể điều khiển được cả những máy in vừa mới ra, sau khi người ta phát hành Windows rất lâu.
Quay lại với ví dụ animal ở trên, nếu bạn bỏ tính đa hình bằng cách bỏ đi sự thừa kế từ Animal, bạn vẫn gọi được Dog::move và Fish:move, nhưng sau này bạn sẽ không thể tạo ra Bird để sử dụng.
Người ta cũng gọi cách thức đa hình này là đa hình động.
(còn tiếp phần 2 – chuẩn bị tư thế học đa hình theo phong cách hard core nhé)
One thought on “GIẢI THÍCH CÁC KHÁI NIỆM TRONG OOP – TÍNH ĐA HÌNH (Polymorphism)”