Yêu cầu mọi thông tin sao chép từ blog này phải được ghi rõ đầy đủ: Thông tin được sao chép từ "http://www.dangngochoangthanh.blogspot.com".

Cool wallpaper http://www.fancymessage.com

EMOJI KEYBOARD PRO http://emojiselector.com

THƯ VIỆN HÌNH ĐỘNG FLASH ANIMATION: http://flashanimationlibrary.blogspot.ru/

Hệ thống học trực tuyến đang được phát triển và sẽ đưa vào sử dụng vào cuối năm nay. Hãy xem qua một số demo của Học Trực Tuyến.


HỌC TRỰC TUYẾN ĐÃ CUNG CẤP PHIÊN BẢN TRUY CẬP QUA MOBILE http://dangngochoangthanh.blogspot.com/?m=1

XEM KÊNH HỌC TRỰC TUYẾN TRÊN YOUTUBE



Search on This Blog

Saturday, September 11, 2010

Tính đa hình – Polymorphism

Con trỏ trỏ vào lớp cơ sở:
Một trong những tính năng theng chốt của lớp dẫn xuất là con trỏ trỏ vào lớp dẫn xuất sẽ tương thích kiểu với một con trỏ của lớp cơ sở. Đó chính là sự thể hiện của tính đa hình (cùng một lớp cơ sở, nhưng mỗi con trỏ của lớp dẫn xuất có các hình thái thể hiện khác nhau). Tính đa hình này mang lại cho kĩ thuật lập trình hướng đối tượng thêm những ưu điểm trong việc tạo dựng những tính năng đơn giản nhưng hữu dụng và linh hoạt.
Chúng ta sẽ bắt đầu viết chương trình về hình chữ nhật và tam giác. Lớp chữ nhật và tam giác kế thừa từ lớp đa giác và chúng có những phương thức thành viên riêng. Phương thức thành viên này cùng nội dung, nhưng lại có cách thể hiện khác nhau (cùng tính diện tích, nhưng diện tích hình chữ nhật và hình tam giác có công thức tính khác nhau).

Ví dụ Kết quả
#include using namespace std;
class Polygon{
protected:
int w, h;
public:
void setValue(int w, int h){
this->w = w;
this->h = h;
}
};
class Rectangle:public Polygon{
public:
int area(){
return w*h;
}
};
class Triangle:public Polygon{
public:
int area(){
return w*h/2;
}
};
int main()
{
Rectangle rec;
Triangle tri;
Polygon *pol1 = &rec;
Polygon *pol2 = &tri;
pol1->setValue(4, 5);
pol2->setValue(4, 5);
cout<<”Area of Rectangle: “<<
cout<<”Area of Triangle: “<<
return 0;
}
Area of Rectangle: 20 Area of Triangle: 10
Trong hàm main, chúng ta tạo ra hai con trỏ đối tượng của lớp Polygon là pol1 và pol2. Chúng ta truy cập tham chiếu cho rec và tri đến hai con trỏ này, vì chúng là hai đối tượng của lớp dẫn xuất từ Polygon, nên phép gán trong trường hợp này là hợp lệ.
Chỉ có một giới hạn là việc sử dụng *pol1 và *pol2 thay thế cho rec và tri là không thể (ta không thể sử dụng phương thức pol1->area() hay pol2->area()). Bởi vì phương thức area() không phải là một thành viên của Polygon. Để giải quyết vấn đề này, chúng ta sẽ sử dụng phương thức thành viên ảo.
Như bạn thấy trong ví dụ này, hai đối tượng tri và rec là hai đối tượng khác nhau thừa kế từ polygon. Nhưng chúng có cùng phương thức area để tính diện tích của nó. Tuy nhiên, cách tính diện tích của hình chữ nhật và hình tam giác là hoàn toàn khác nhau.
Tính đa hình. Là tính chất thể hiện nhiều hình thái của đối tượng. Các đối tượng khác nhau có thể có cùng phương thức thực thi cùng một hành động. Nhưng mỗi đối tượng lại thực thi hành động theo cách riêng của mình, mà không giống nhau cho tất cả các đối tượng.
Thành viên ảo
Để quy định một phương thức là ảo, chúng ta sử dụng từ khóa virtual. Nhờ vào phương thức ảo, ta có thể định nghĩa lại một phương thức thành viên của lớp cơ sở bên trong lớp dẫn xuất.
Ví dụ Kết quả
#include using namespace std;
class Polygon{
protected:
int w, h;
public:
void setValue(int w, int h){
this->w = w;
this->h = h;
}
virtual int area(){
return (0);
};
};
class Rectangle:public Polygon{
public:
int area(){
return w*h;
}
};
class Triangle:public Polygon{
public:
int area(){
return w*h/2;
}
};
int main()
{
Rectangle rec;
Triangle tri;
Polygon pol;
Polygon *pol1 = &rec;
Polygon *pol2 = &tri;
Polygon *pol3 = &pol;
pol1->setValue(4, 5);
pol2->setValue(4, 5);
pol3->setValue(4, 5);
cout<<”Area of Rectangle: “<area()<
cout<<”Area of Triangle: “<area()<
cout<<”Area of Polygon: “<area()<
return 0;
}
Area of Rectangle: 20 Area of Triangle: 10
Area of Polygon: 0
Nếu gỡ bỏ từ khóa virtual thì kết quả sẽ là 0, 0 và 0. Sở dĩ là vì trong trường hợp này area() là phương thức thành viên của lớp Polygon. Dù phương thức này đã bị quá tải trong các lớp thành viên, nhưng các đối tượng *pol1, *pol2, *pol3 là các đối tượng của lớp Polygon, nên khi gọi phương thức area() là gọi đến phương thức area() của Polygon.
Như vậy, với từ khóa virtual, các phương thức của các lớp dẫn xuất có thể thực hiện các phương thức thành viên riêng mà phương thức thành viên đó có thể trùng tên với phương thức thành viên của lớp cơ sở.
Bạn lưu ý rằng, một số ngôn ngữ quy định virtual là mặc định cho các phương thức thành viên (nếu không khai báo từ khóa này) như Java, C#. Nhưng ngôn ngữ lập trình C++ thì không như vậy. Trong C++, từ khóa virtual là không mặc định cho các phương thức thành viên.
Khi giải thích ví dụ trên, tôi có sử dụng thêm khái niệm quá tải. Bạn cần lưu ý, khái niệm chồng chất hàm thành viên khác với khái niệm quá tải hàm thành viên (đôi lúc gọi là ghi đè hàm thành viên). Chồng chất hàm thành viên (overload) là việc quy định nhiều hàm cùng tên nhưng khác tham số, các hàm này là thành viên của cùng một lớp nội tại hoặc các hàm toàn cục. Trong khi đó, quá tải hàm thành viên (override) là các hàm có cấu trúc giống nhau nhưng thuộc hai lớp khác nhau và một trong số chúng thừa kế từ lớp còn lại, khi đó, ta nói rằng phương thức của lớp cha đã bị phương thức của lớp con quá tải.
Lớp cơ sở trìu tượng
Lớp cơ sở trừu tượng (abstract base class) có nhiều nét tương đồng với lớp Polygon của ví dụ trên. Chỉ có sự khác biệt là phương thức area() của lớp Polygon không thực hiện hoàn toàn chức năng của một hàm mà đơn thuần ta sẽ khai báo virtual int area() = 0;. Nghĩa là bạn chỉ bổ sung vào giá trị 0 sau toán tử gán. Với sự khai báo dạng này, người ta gọi là phương thức ảo thuần túy (pure virtual function). Một lớp được gọi là lớp cơ sở trìu tượng, khi nó chứa ít nhất một phương thức thành viên ảo thuần túy.
Sự khác biệt căn bản giữa lớp cơ sở trìu tượng và lớp đa hình là lớp cơ sở trìu tượng không thể tạo ra một sự thể hiện cho nó. Nghĩa là bạn không thể viết Polygon pol; như trong ví dụ trên. Bạn chỉ có thể sử dụng một con trỏ, để trỏ đến nó và sử dụng các tính năng đa hình của nó mà thôi.
Ví dụ Kết quả
#include using namespace std;
class Polygon{
protected:
int w, h;
public:
void setValue(int w, int h){
this->w = w;
this->h = h;
}
virtual int area() = 0;
};
class Rectangle:public Polygon{
public:
int area(){
return w*h;
}
};
class Triangle:public Polygon{
public:
int area(){
return w*h/2;
}
};
int main()
{
Rectangle rec;
Triangle tri;
/* Polygon pol;  Phát sinh lỗi vì Polygon là một lớp trìu tượng, ta không thể tạo một thể hiện cho lớp trìu tượng */
Polygon *pol1 = &rec;
Polygon *pol2 = &tri;
pol1->setValue(4, 5);
pol2->setValue(4, 5);
cout<<”Area of Rectangle: “<area()<
cout<<”Area of Triangle: “<area()<
return 0;
}

1 comment: