Kỹ thuật lập trình - Chương 5: Tính kế thừa

Ngoài việc nhóm các đối tượng có cùng tập thuộc tính/hành vi lại với nhau, con người thường nhóm các đối tượng có cùng một số thuộc tính/ hành vi

Ví dụ: nhóm tất cả xe chạy bằng động cơ thành một nhóm, rồi phân thành các nhóm nhỏ hơn tuỳ theo loại xe (xe ô tô, xe tải,.)

 

pptx51 trang | Chia sẻ: Mr Hưng | Lượt xem: 803 | Lượt tải: 0download
Bạn đang xem trước 20 trang nội dung tài liệu Kỹ thuật lập trình - Chương 5: Tính kế thừa, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
Chương 5. Tính kế thừa (Inheritance)TRẦN MINH THÁIEmail: minhthai@itc.edu.vnWebsite: www.minhthai.edu.vn Cập nhật: 10 tháng 04 năm 2015Nội dungGiới thiệuKhái niệm kế thừaĐơn kế thừaĐa kế thừaLớp cơ sở ảoGiới thiệu [1/10]Ngoài việc nhóm các đối tượng có cùng tập thuộc tính/hành vi lại với nhau, con người thường nhóm các đối tượng có cùng một số thuộc tính/ hành viVí dụ: nhóm tất cả xe chạy bằng động cơ thành một nhóm, rồi phân thành các nhóm nhỏ hơn tuỳ theo loại xe (xe ô tô, xe tải,...)Giới thiệu [2/10]Mỗi nhóm con là một lớp các đối tượng tương tự, nhưng giữa các nhóm con có chung một số đặc điểmQuan hệ giữa các nhóm con với nhóm lớn được gọi là quan hệ “là một” (is-a)Giới thiệu [3/10]Ví dụ:Một cái xe ô tô “là một” xe động cơMột cái xe tải “là một” xe động cơMột cái xe máy “là một” xe động cơ Dùng cấu trúc hướng đối tượng để định nghĩa quan hệ “là một”Giới thiệu [4/10]Các đối tượng được nhóm lại thành một lớp thì có cùng tập thuộc tính và hành viMọi đối tượng xe động cơ có cùng tập thuộc tính và hành vi Mọi đối tượng xe tải có cùng tập thuộc tính và hành viGiới thiệu [5/10]Mối liên kết giữa các lớp trong quan hệ “là một” xuất phát từ thực tế rằng các lớp con cũng có mọi thuộc tính/ hành vi của lớp cha, và cộng thêm các thuộc tính/ hành vi khácGiới thiệu [6/10]Lớp cha – superclass (hoặc lớp cơ sở - base class)Lớp tổng quát hơn trong mối quan hệ “là một”Các đối tượng thuộc lớp cha có cùng tập thuộc tính và hành viGiới thiệu [7/10]Lớp con – subclass (hoặc lớp dẫn xuất – derived class)Lớp cụ thể hơn trong một quan hệ “là một”Các đối tượng thuộc lớp con có cùng tập thuộc tính và hành vi (do kế thừa từ lớp cha), kèm thêm tập thuộc tính và hành vi của riêng lớp conGiới thiệu [8/10]Quan hệ “là một” còn gọi là sự kế thừa (inheritance)Ta nói rằng lớp con “kế thừa từ” lớp cha, hoặc lớp con “được dẫn xuất từ” lớp cha  Kế thừa là quá trình tạo nên lớp mới bằng cách dẫn xuất từ lớp cũGiới thiệu [9/10]Ưu điểm của việc kế thừaTiết kiệm thời gian và công sứcTái sử dụng lại những lớp có sẵnGiảm lượng code phải thiết kế, viết, kiểm traTránh trùng lắp codeRút ngắn thời gian giúp LTV tập trung vào mục tiêuGiúp phân loại và thiết kế lớp dễ dàng, dễ quản lýGiới thiệu [10/10]Phân loạiĐơn kế thừa (single inheritance): chỉ có một lớp chaĐa kế thừa (multiple inheritance): có nhiều lớp chaSơ đồ quan hệ đối tượng [1/3] (Object Relationship Diagram – ORD)Thể hiệnSự khác nhau giữa lớp cơ sở và lớp dẫn xuấtSự khác nhau giữa các lớp dẫn xuấtSơ đồ quan hệ đối tượng [2/3]Biểu diễn các thành phần:private: thêm dấu trừ phía trước tênpublic: thêm dấu cộng phía trước tênSơ đồ quan hệ đối tượng [3/3]Đối với những lớp dẫn xuất, chỉ cần liệt kê các thuộc tính/ hành vi mà lớp cơ sở không có Đơn giản hoá sơ đồNhấn mạnh các điểm khác biệtCây kế thừa [1/2]Các quan hệ kế thừa luôn được biểu diễn với các lớp dẫn xuất đặt dưới lớp cơ sở để nhấn mạnh bản chất phả hệ của quan hệCây kế thừa [2/2]Kế thừa phần lớn các thành viên dữ liệu và phương thức của lớp cơ sở Lớp dẫn xuấtCó thể bổ sung thêm các thành viên dữ liệu mới và các phương thức mới (ngoại trừ constructor, destructor)Lớp cơ sở trực tiếpLớp cơ sởLớp cơ sở gián tiếpClass AClass BClass CKế thừa vs Quan hệ khácĐây là quan hệ không dựa trên kế thừa Mối quan hệ này gọi là quan hệ “có một” (has-a) cũng được gọi là quan hệ bao gộp (aggregation)Đơn kế thừa [1/2]Cú phápclass derived_class_name : type_of_inheritance base_class_name {member_list }; type_of_inheritance là public, protected hoặc private. Mặc định là private.Từ khoá truy xuất của thuộc tính: public, private, protected.Đơn kế thừa [2/2]Thuộc tính truy xuất thành viên của lớp cơ sởKiểu kế thừapublicprotectedprivatepublicpublic trong lớp dẫn xuấtprotected trong lớp dẫn xuấtprivate trong lớp dẫn xuấtprotectedprotected trong lớp dẫn xuấtprotected trong lớp dẫn xuấtprivate trong lớp dẫn xuấtprivateDấu trong lớp dẫn xuấtDấu trong lớp dẫn xuấtDấu trong lớp dẫn xuấtpublicprotectedprivateVD - đơn kế thừa [1/4]class CMyPoint{ protected: float x,y; public: CMyPoint(float a= 0, float b= 0); void SetPoint(float a, float b); float GetX() const { return x; } float GetY() const { return y; } void Print() const;};VD - đơn kế thừa [2/4]CMyPoint::CMyPoint(float a, float b){ SetPoint(a, b);}void CMyPoint::SetPoint(float a, float b){ x = a; y = b;}void CMyPoint::Print() const{ cout Print(); //CMyPoint::Print();UpcastSự chuyển kiểu [4/7]Tương tự đối với biến tham chiếuUpcast là quá trình tương tác với thực thể của lớp dẫn xuất như thể nó là thực thể của lớp cơ sởvoid Fun(A & a){ }B b;Fun(b);ABSự chuyển kiểu [5/7]Upcast thường sử dụng trong các tham số của hàmTham số hình thức là một con trỏ/tham chiếu đến lớp cơ sở được yêu cầunhưng tham số thực là con trỏ/tham chiếu đến lớp dẫn xuất cũng được chấp nhậnSự chuyển kiểu [6/7]Downcast là quy trình ngược lại, đổi kiểu con trỏ/tham chiếu tới lớp cơ sở thành con trỏ/tham chiếu tới lớp dẫn xuấtDowncast là quy trình rắc rối hơn và có nhiều điểm không an toànĐây không phải là một quy trình tự động - nó luôn đòi hỏi đổi kiểu tường minh (explicit type cast)Sự chuyển kiểu [7/7]Nếu ta biết chắc chắn một con trỏ lớp cơ sở đang trỏ tới một lớp dẫn xuất, ta có thể tự đổi kiểu cho con trỏ lớp cơ sở bằng cách sử dụng chuyển kiểu tường minhCMyPoint p(100,50);CCircle *c;c = &p; //ErrorCCircle *c = new CCircle(100,50,50); CMyPoint *p = c; //UpcastCCircle *c2 = static_cast(p); //Explicit downcastĐa kế thừa [1/6]Là khả năng một lớp có nhiều lớp cơ sởCây kế thừa phức tạp lên rất nhiềuCó thể sinh ra các vấn đề nhập nhằng (do các tên trùng nhau thành viên)BicycleFrameWheelPersonFishPersonFishĐa kế thừa [2/6]Cú phápclass derived_class_name : type_of_inheritance base_class_name1, type_of_inheritance base_class_name2, { member_list }; Đa kế thừa [3/6]class CCircle{ protected: float radius; public: CCircle(float r) { radius=r; } float Area() { return radius*radius*3.14f; }};class CTable{ protected: float height; public: CTable(float h) { height=h; } float Height() { return height; }};class CRoundTable: public CTable, public CCircle{ private: int color; public: CRoundTable(float h, float r, int c); int Color() { return color; }};CRoundTable::CRoundTable(float h, float r, int c):CTable(h), CCircle(r){ color=c;}Đa kế thừa [4/6]CRoundTable table(1, 0.5f, 5);cout << "Thong tin ve ban:" << endl;cout << "Chieu cao:" << table.Height() << endl;cout << "Dien tich:" << table.Area() << endl;cout << "Mau: ” << table.Color << endl;Đa kế thừa – Constructor & destructor [5/6]Các tham số của constructor của tất cả các lớp cơ sở này được khai báo trong constructor của lớp dẫn xuất và constructor cơ sở cũng phải được khởi tạoConstructor lớp cở sở xuất hiện trước sẽ thực hiện trước và cuối cùng mới tới constructor lớp dẫn xuấtĐối với destructor có trình tự thực hiện theo thứ tự ngược lạiĐa kế thừa [6/6]class A { public: void Method(); };class B { public: void Method(); };class C: public A, public B { };C c;c.Method();//ambiguity //A::Method() or B::Method() ??? C c;c.A::Method();c.B::Method();Lớp cơ sở ảo – Virtual base class [1/4]DBCAxxxclass A { public: int x; };class D: public B, public C{};D d;d.x = 3; //ambiguityd.B::x = 5; d.C::x = 7;Giải pháp tạm thờiclass B: public A{};class C: public A{};Giải pháp: Khai báo lớp A là lớp cơ sở ảo cho cả 2 lớp B và C Lớp cơ sở ảo [2/4]Không thể khai báo hai lần cùng một lớp trong danh sách của các lớp cơ sở cho một lớp dẫn xuất.Tuy nhiên vẫn có thể có trường hợp cùng một lớp cơ sở được đề cập nhiều hơn một lần Điều này phát sinh lỗi vì không có cách nào để phân biệt hai lớp cơ sở gốcLớp cơ sở ảo [3/4]Các lớp cơ sở ảo sẽ được kết hợp tạo ra một lớp cơ sở duy nhất cho bất kỳ lớp dẫn xuất nào thừa hưởng từ chúngclass A { public: int x; };class B: virtual public A{};class C: virtual public A{};class D: public B, public C{};D d;d.x = 3; //OKLớp cơ sở ảo [4/4]ABCDE2FE1?Kết luậnTrong thực tế, có một loạt các vấn đề tiềm tàng liên quan đến đa kế thừa, phần lớn là do rắc rối vì nhập nhằngCó thể không bao giờ cần dùng đến đa kế thừa, nhưng cũng có những tình huống mà đa kế thừa là lời giải tốt nhất (và có thể là duy nhất)Nếu sử dụng đa kế thừa, nhất thiết phải cân nhắc về các xung đột có thể nảy sinh trong khi sử dụng các lớp có liên quanQ&A

Các file đính kèm theo tài liệu này:

  • pptxchuong5_tinhkethua_8199.pptx