Menu Close

Kế thừa (Inheritance)

Một số lý thuyết

  • Đôi khi ta tạo một class mới có các thuộc tính, chức năng như cái đã có. Tại sao ko
    tận dụng cái đã có. Có thể thực hiện thông qua kế thừa (inheritance). Class mới gần giống như là clone bản gốc, thêm, hiệu chỉnh lại.
    Class gốc gọi là base, super, parent class, còn class clone là
    dẫn xuất (derived), kết thừa, con.

    • *Ví dụ: trong ứng dụng xây dựng công cụ hỗ trợ thiết kế giao diện. Ta thấy có
      nhiều loại control khác nhau như button, textbox, selection bar, … Mỗi loại đó
      hệ thống điều hiểu là control và có chung thuộc tính về vị trị, màu sắc, kích
      thước, hành vi draw… Vậy ta có thể xây dựng một base class là control và các
      dẫn xuất là button, textbox, selection bar và hiệu chỉnh lại cách vẽ phù hợp
      cho từng control,….*
  • Khi kế thừa một class từ class đã có thì class mới sẽ có tất cả các thuộc
    tính của base class (có thể các private không thể truy cập trực tiếp nhưng chúng
    vẫn tồn tại trong class con), cũng như có interface (các hành vi) như base class
    tức là các message gửi đến base class thế nào thì cũng có thể gửi đến class dẫn
    xuất như thế. –> class dẫn xuất cùng loại với base class. Ví dụ: mọi control
    đều có thể draw và tất cả các class dẫn xuất của nó button, textbox, … đều có
    thể draw.
  • Derived class nhưng chúng không phải hoàn toàn là như base class. Derived
    class có thêm hành vi mà base class trên lý thuyết hoàn toàn không có thì ta
    có thể đơn giản thêm mới hành vi này vào derived class. Môt tình huống khác,
    Derived class có cùng hành vi nhưng sẽ thực hiện hành vi này theo thứ tự khác.
    Khi đó Derived class cần được ghi đè (Overloading) hành vi đó.
  • Nếu derived class kế thừa và có cùng interface (không thêm hành mới) so với
    base class thì ta nói đó là pure substitution hay đó là quan hệ is-a. **Derived
    class is a base class** (Ex: Button is a control). Nhưng nếu Derived class có
    xây dựng thêm hành vi mới thì lúc đó ta gọi đó là quan hệ is like a.
    Ta cũng thể có gọi hai quan hệ is-a, is-like-a đều là quan hệ is-a
    để thuận tiện trong việc diễn đạt và xác định kế thừa khi phân tích bài toán.
  • Môt tình huống, ta xây dựng một hệ thống kế thừa, và ta muốn quản lý base class
    thay cho từng derived class cụ thể. Việc quản lý từng derived cụ thể sẽ rất khó
    và việc hiệu chỉnh nhiều vì mỗi lần một derived class mới được sinh ra thì ta
    cần cập nhật lại trong khi interface mà bên ngoài tương tác vào là như nhau. Cụ
    thể, Ta có một nơi mà nhiệm vụ của nó là nhận vào là các control (không phân
    biệt control loại nào) và tiến hành gọi draw của control để vẽ. Khi ta sử dụng
    quản lý dựa trên based class thì việc này khá đơn giản. Nhưng nếu không quản lý
    dựa trên base class thì mọi việc sẽ trở nên nhiều hơn khi đó cứ mỗi derived
    class được sinh ra thì một nơi riêng chuyên biệt cho nó được tạo ra – việc này
    trông khá stupid vì nội dung các nơi này đều như nhau, đều chỉ gọi 1 chức năng draw của control. Vì vậy việc quản lý do
    base class có một vấn đề đặt ra, làm sao ta có thể vẽ đúng từng control (vì mỗi
    control có cách hiển thị khác nhau) trong khi chỉ sử dụng đúng chức năng draw
    của control tổng quát. Vấn đề có thể được giải quyết với đa hình.
  • Khi phân tích và thiết kế chú ý: trong quan hệ từ thực tế vấn tồn tại một loại
    quan hệ composition. Ta chỉ sử dụng kế thừa cho các class có quan hệ is-a (đọc thêm ở bài giới thiệu về OOP)Những nội dung sẽ tiếp tục được bổ sung

Trong C++

Kế thừa C++ với cú pháp cơ bản như sau:

class A
{
    public:
    //Các thành phần public
    protected:
    //Các thành phần protected
    private:
    //Các thành phần private
}
---
//Kế thừa kiểu public
class B: public A
{
    //Ngoài các thành phần mới của riêng B
    //Các thành phần public của A sẽ là public của B
    //Các thành phần protected của A sẽ là protected của B
    //Các thành phần private của A sẽ tồn tại ẩn và không được gọi trực tiếp
    //trong derived class.
}
//Kế thừa kiểu protected
class C: protected A
{
    //Ngoài các thành phần mới của riêng C
    //Các thành phần public, protected của A sẽ là protected của C.
    //Còn private thì tồn tại ẩn không truy cập trực tiếp
}
//Kế thừa kiểu private
class D: private A
{
    //Ngoài các thành phần mới của riêng D
    //Các thành phần public, protected của A thành private của D. còn private thì
    //tồn tại ẩn không truy cập trực tiếp.
}Kiểu kế thừa hay sử dụng nhất vẫn là public.

Leave a Reply

Your email address will not be published. Required fields are marked *