Tính đa hình (Polymorphism) trong C++

Tính đa hình

Tính đa hình là khả năng mà một đối tượng được xử lý theo nhiều đối tượng khác bằng cách dùng chung một tên phương thức hay giao diện. Nói cách khác, tính đa hình trong C++ được xem như một trong các tính năng hàng đầu của lập trình hướng đối tượng. Trong bài viết này, các bạn sẽ hiểu được tính đa hình là gì, những dạng đa hình hay vai trò của đa hình.

Tổng quan về tính đa hình trong C++

Tính đa hình trong C++ được hiểu như việc hỗ trợ một đối tượng trong việc thực thi đa dạng những hành vi tùy theo môi trường sử dụng. Nó là một đặc tính thuần túy trong ngành lập trình hướng đối tượng. Để giúp các bạn hiểu sâu về tính đa hình, chúng tôi sẽ trình bày ví dụ minh họa sau.

Tính đa hình là thuộc tính quan trọng trong C++
Hình 1. Tính đa hình là thuộc tính quan trọng trong C++

Ví dụ:

#include <iostream>

using namespace std;

class Shape {

protected:

int width, height;

public:

Shape(int w = 0, int h = 0) {

width = w;

height = h;

}

virtual int area() {

cout << "Parent class area: " << endl;

return 0;

}

};

class Rectangle: public Shape {

public:

Rectangle(int w = 0, int h = 0): Shape(w, h) {

}

int area() {

cout << "Rectangle class area: " << endl;

return (width * height);

}

};

class Triangle: public Shape {

public:

Triangle(int w = 0, int h = 0): Shape(w, h) {

}

int area() {

cout << "Triangle class area: " << endl;

return (width * height / 2);

}

};

int main() {

Shape *shape;

Rectangle rec(10, 7);

Triangle tri(10, 5);

shape = &rec;

shape->area();

shape = &tri;

shape->area();

return 0;

}

Người dùng có thể định nghĩa cả ba lớp ‘Shape’, ‘Rectangle’ hay ‘Triangle’. Lúc này, lớp ‘Shape’ sẽ dùng phương thức ảo ‘area()’ ngược lại cả ‘Triangle’ hay ‘Rectangle’ kế thừa từ lớp ‘Shape’ và có thể định nghĩa hàm ‘area()’ lần nữa cho chính nó. Mặt khác, hai đối tượng ‘tri’ hay ‘rec’ có thể được tạo ra trong hàm ‘main()’.

Có bao nhiêu loại đa hình trong C++?

Trên thực tế, có hai loại đa hình trong C++ gồm: đa hình run-time và đa hình compile-time. Hãy cùng nhau tìm hiểu đặc điểm và ví vụ của hai loại đa hình này nhé.

Các loại đa hình phổ biến trong C++
Hình 2. Các loại đa hình phổ biến trong C++

1. Đa hình compile-time

Loại đa hình này được biết đến như đa hình tĩnh. Nói cách khác, loại đa hình mà những quyết định liên quan tới hàm có thể được thực thi ở trong quá trình biên dịch. Những đối tượng được dùng sẽ ảnh hưởng đến thời điểm biên dịch. Chúng ta có thể dùng kỹ thuật templates để thực hiện loại đa hình tĩnh này.

Ví dụ:

template <typename T>

T max(T a, T b) {

return (a > b) ? a : b;

}

int main() {

int x = 5, y = 10;

float a = 1.2, b = 3.4;

cout << max(x, y) << endl; // trả về 10

cout << max(a, b) << endl; // trả về 3.4

return 0;

}

Từ đoạn code trên, người dùng sử dụng hàm template ‘max()’ để tìm kiếm giá trị lớn nhất giữa hai đối tượng bất kỳ mà giống nhau về kiểu dữ liệu. Lúc này, kiểu dữ liệu sẽ được phán quyết và thực thi tại lúc biên dịch.

2. Đa hình run-time

Đa hình run-time là dạng đa hình mà những quyết định liên quan đến phương thức sẽ có thể thực thi tại lúc runtime. Chúng ta dùng kỹ thuật kế thừa hay hàm ảo để thực hiện đa hình run-time (đa hình động)

Ví dụ:

#include <iostream>

using namespace std;

class Shape {

protected:

int width, height;

public:

Shape(int w = 0, int h = 0) {

width = w;

height = h;

}

virtual int area() {

cout << "Parent class area: " << endl;

return 0;

}

};

class Rectangle: public Shape {

public:

Rectangle(int w = 0, int h = 0): Shape(w, h) {

}

int area() {

cout << "Rectangle class area: " << endl;

return (width * height);

}

};

class Triangle: public Shape {

public:

Triangle(int w = 0, int h = 0): Shape(w, h) {

}

int area() {

cout << "Triangle class area: " << endl;

return (width * height / 2);

}

};

int main() {

Shape *shape;

Rectangle rec(10, 7);

Triangle tri(10, 5);

shape = &rec;

Những ưu điểm của tính đa hình trong C++

Tại sao chúng ta phải áp dụng tính đa hình trong C++? Phần này sẽ giúp các bạn hiểu rõ thêm về các lợi ích mà tính đa hình đem lại cho dự án của bạn.

1. Linh hoạt: tính đa hình hỗ trợ những đối tượng trong việc thay đổi hành vi dựa trên môi trường sử dụng. Lúc này, đoạn code của người dùng sẽ linh hoạt và đơn giản hóa trong việc bảo trì.

2. Tái sử dụng: tính đa hình sẽ giúp bạn dùng lại những đoạn mã đã tồn tại trong lớp cơ sở hay cài lại những hàm trong những lớp dẫn xuất. Từ đó, các bạn có thể tránh tốn thời gian trong việc lặp lại mã và quá trình dùng lại mã sẽ đơn giản và thuận tiện hơn.

3. Tính đa dạng: sẽ xuất hiện vô vàn những hình thái khác nhau trên một đối tượng trong dự án khi bạn sử dụng tính đa hình. Bạn có thể thao tác trên nhiều loại đối tượng thông qua việc khai thác trên cùng một đoạn mã.

4. Đơn giản hóa: Chương trình của bạn chắc chắn sẽ đơn giản và ít phức tạp đi rất nhiều thông qua việc phân chia những tính năng khác nhau trong cùng một đối tượng thành những hàm riêng lẻ. Từ đó, đoạn mã trong chương trình sẽ đơn giản hóa đi rất nhiều và chúng ta có thể hiểu chúng nhanh hơn.

Chương trình sẽ đơn giản hơn nhờ vào tính đa hình
Hình 3. Chương trình sẽ đơn giản hơn nhờ vào tính đa hình

Nhìn chung, tính đa hình là cực kỳ thiết yếu trong ngôn ngữ lập trình C++. Nó sẽ hỗ trợ bạn trong việc tạo mã nhanh, thuận tiện, sử dụng lại và cực kỳ dễ bảo trì.

Phương thức ảo là gì?

Phương thức ảo (hàm ảo) là một hàm được khai báo trong lớp cơ sở tương ứng với từ khóa “virtual” nhằm hỗ trợ những lớp dẫn xuất có thể ghi đè nó kèm theo thực thi theo phương pháp chuyền biệt.

Không những vậy, nó hỗ trợ những đối tượng tạo ra từ những lớp dẫn xuất đã dùng những phương thức triển khai từ lớp cơ sở của chúng.

Ví dụ:

#include <iostream>

using namespace std;

class Shape {

public:

virtual void draw() {

cout << "Drawing a Shape" << endl;

}

};

class Circle : public Shape {

public:

void draw() {

cout << "Drawing a Circle" << endl;

}

};

class Square : public Shape {

public:

void draw() {

cout << "Drawing a Square" << endl;

}

};

int main() {

Shape* shape1 = new Circle();

Shape* shape2 = new Square();

shape1->draw();

shape2->draw();

delete shape1;

delete shape2;

return 0;

}

Người dùng có thể định nghĩa lớp ‘Shape’ với hàm ảo “draw” và cả hai lớp dẫn xuất Circle hay Square để ghi đè hàm tạo tiền đề cho việc vẽ hình tròn hay hình vuông. Đối với hàm main, sẽ có hai đối tượng được khởi tạo gồm: Circle và Square. Sau đó, gọi hàm “draw” thông qua con trỏ đến lớp cơ sở “Shape”.

Sau đó, hãy chạy chương trình và kết quả là:

Drawing a Circle

Drawing a Square

Nó chứng minh là hàm “draw” được gọi sẽ phụ thuộc theo lớp trên đối tượng đã khởi tạo mà là Square hay Circle. Tóm lại, tính năng hàm ảo hỗ trợ người dùng trong việc tạo ra những đối tượng đa hình cũng như giải quyết chúng hiệu quả.

Thế nào là phương thức thuần ảo trong C++?

Khi đã biết được phương thức ảo thì tiếp đến chúng ta cũng nên tìm hiểu và nghiên cứu đến phương thức thuần ảo trong C++. Đây là phương thức nằm trong lớp trừu tượng trong ngôn ngữ lập trình C++.

Không những vậy, phương thức này sẽ không có định nghĩa và thường đi với từ khóa “=0” ở cuối khai báo phương thức.

Ví dụ:

class Shape {

public:

virtual void draw() = 0;

};

Như các bạn đã thấy, lớp ‘Shape’ được ví như lớp trừu tượng. Phương thức ‘draw()’ đóng vai trò là hàm thuần ảo. Lớp ‘Shape’ chỉ được dùng cho việc tạo những lớp con khác mà không hỗ trợ khởi tạo.

Kế đến, khi lớp con được kế thừa từ lớp ‘Shape’ thì nó sẽ phải cài lại hàm ‘draw()’ theo phương pháp chuyên biệt. Nếu không, lỗi biên dịch sẽ xuất hiện. Nhìn chung, phương thức thuần ảo hỗ trợ làm ra giao diện chung cho những lớp con, thậm chí phát triển ứng dụng đơn giản và ít gây ra lỗi phát sinh trong dự án.

Lời kết

Chúng tôi đã tổng hợp những thông tin quan trọng liên quan đến tính đa hình trong C++ kèm theo những khía cạnh liên quan như: phương thức ảo hay thuần ảo. Cuối cùng, hy vọng bài viết sẽ giúp bạn tiếp cận đến tính đa hình dễ dàng hơn trong tương lai và đừng quên để lại ý kiến đóng góp bên dưới bài viết này nhé.

Rate this post

Trả lời

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *