Tính đa hình trong OOP là một nội dung không mới, mặc dù vậy ít ai thực sự hiểu rõ về định nghĩa này. Bài post sẽ chỉ rõ về Tính đa hình cũng như giới thiệu về những loại đa hình mà bạn phải cần biết.
Tính đa hình là gì ?
Sự kế thừa trong C++ cho phép có sự tương ứng giữa lớp cơ sở & các lớp dẫn xuất trong sơ đồ thừa kế:
- Một con trỏ có kiểu lớp cơ sở luôn có thể trỏ đến địa chỉ của một đối tượng của lớp dẫn xuất.
- Tuy vậy, khi thực hiện lời gọi một phương thức của lớp, trình biên dịch sẽ quan tâm đến kiểu của con trỏ chứ không phải đối tượng mà con trỏ đang trỏ tới: phương thức của lớp mà con trỏ có kiểu được gọi chứ không phải phương thức của đối tượng mà con trỏ đang trỏ tới được gọi.
Ví dụ: Lớp mayAcer kế thừa từ lớp Mayvitinh
, cả hai lớp này đều khái niệm phương thức show()
classMayvitinhpublic:voidshow()
cout <<"mayvitinh"<< endl;
;classmayAcer:publicMayvitinhpublic:voidshow()
cout <<"mayAcer"<< endl;
;
Lúc đó, nếu ta khai báo một con trỏ lớp mayAcer
, tuy vậy lại trỏ vào địa chỉ của một đối tượng lớp Mayvitinh
:
mayAcer may1;
Mayvitinh *tenmay =&may1;
tenmay->show();
Thì chương trình sẽ gọi đến phương thức show()
của lớp Mayvitinh
, mà không gọi tới phương thức show()
của lớp mayAcer
.
Để giải quyết điều này, chúng ta cần sử dụng đến tính đa hình trong Lập trình hướng đối tượng. Mình sẽ chỉ rõ chi tiết hơn ở bên dưới.
Khái niệm tính đa hình trong OOP
Đa hình (polymorphism) nghĩa là có nhiều hình thái khác nhau. Tiêu biểu là, đa hình xuất hiện khi có một cấu trúc cấp bậc của các lớp & chúng liên quan với nhau bởi tính kế thừa.
Mình lấy một Ví dụ thực thế nhé:
Một người cùng một lúc có thể có đặc điểm khác nhau. giống như một người đàn học sinh thời là một người con trai, một người bạn, một người anh. vì lẽ đó, cùng một người sở hữu những hành vi khác nhau trong các tình huống không giống nhau. Điều này còn được gọi là đa hình.
Đa hình được coi là một trong những tính năng cần thiết của Lập trình hướng đối tượng.
>>> Xem thêm: Lỗi Syntax trong lập trình và những điều bạn cần biết
Các loại đa hình mà bạn cần biết
Tính đa hình trong OOP gồm có hai loại: Đa hình thời gian chạy (Runtime Polymorphism) & Đa hình thời gian biên dịch (Compile Time Polymorphism).
Theo đấy, Tính đa hình cho phép một phương thức thực thi những hành vi khác nhau theo hai hướng: sử dụng phương thức ghi đè (method overriding) hoặc phương thức nạp chồng (method overloading).
Tính đa hình trong OOP
1.Đa hình thời gian biên dịch
Đa hình thời gian biên dịch sử dụng phương thức nạp chồng. Do dùng chung một cái tên cho nhiều phương thức, nên ta phải cho java biết cần phải gọi phương thức nào để thực thi, java dựa vào sự khác nhau về số lượng đối cũng giống như kiểu dữ liệu của các đối này để phân biệt các phương thức trùng tên đó..
2. Runtime Polymorphism:
Các bàn còn nhớ VD đầu tiên của bài không.
#includeusingnamespace std;classMayvitinhpublic:voidshow()
cout <<"mayvitinh"<< endl;
;classmayAcer:publicMayvitinhpublic:voidshow()
cout <<"mayAcer"<< endl;
;intmain()
mayAcer may1;
Mayvitinh *tenmay =&may1;
tenmay->show();
Có thể thấy chương trình một khi chạy sẽ gọi đến phương thức show()
của lớp Mayvitinh
, mà không gọi tới phương thức show()
của lớp mayAcer
.
Vậy để chương trình gọi tới phương thức show()
của lớp mayAcer
ta sử dụng hàm ảo virtual
như sau:
#includeusingnamespace std;classMayvitinhpublic:virtualvoidshow()
cout <<"mayvitinh"<< endl;
;classmayAcer:publicMayvitinhpublic:voidshow()
cout <<"mayAcer"<< endl;
;intmain()
mayAcer may1;
Mayvitinh *tenmay =&may1;
tenmay->show();
Một khi biên dịch chương trình sẽ có kết quả:
Trong Ví dụ trên mình đã thêm Keyword virtual
vào hàm show()
trong lớp cơ sở Mayvitinh
.
Từ khóa virtual
này dùng để khai báo một hàm là hàm ảo.
Khi khai báo hàm ảo với Keyword virtual
nghĩa là hàm này sẽ được gọi theo loại đối tượng được trỏ (hoặc tham chiếu), chứ không phải theo loại của con trỏ (hoặc tham chiếu). Và vấn đề này dẫn đến kết quả khác nhau:
- Nếu không khai báo hàm ảo
virtual
trình biên dịch sẽ gọi hàm tại lớp cở sở - Nếu sử dụng hàm ảo
virtual
trình biên dịch sẽ gọi hàm tại lớp dẫn xuất
Khi nhận thấy có khai báo virtual trong lớp cơ sở, trình biên dịch sẽ chèn vào mỗi đối tượng của lớp cơ sở & các lớp dẫn xuất của nó một con trỏ chỉ đến bảng phương thức ảo (virtual function table). Con trỏ đó có tên là vptr (virtual pointer).
Bảng phương thức ảo là nơi chứa các con trỏ chỉ đến đoạn chương trình đã biên dịch ứng với các phương thức ảo. Mỗi lớp có một bảng phương thức ảo. Trình biên dịch chỉ lập bảng phương thức ảo khi bắt đầu có việc tạo đối tượng của lớp. Đến khi chương trình chạy, phương thức ảo của đối tượng mới được nối kết và thi hành thông qua con trỏ vptr.
Kết
Tổng kết, Tính đa hình là một thuộc tính hay mà lập trình viên nên tận dụng. Mong rằng qua bài post, các bạn có thể có góc nhìn cụ thể hơn về Tính đa hình trong OOP.
Nhật Minh – Tổng hợp và bổ sung
Nguồn: codelearn.io, vn.got-it.ai, kungfutech.edu.vn
Bình luận về chủ đề post