Kế thừa trong Lập trình hướng đối tượng | How Kteam

Dẫn nhập

Ở các bài học trước, chúng ta đã cùng nhau tìm hiểu về TỪ KHÓA STATIC TRONG OOP C#. Hôm nay chúng ta sẽ cùng tìm hiểu về Kế thừa trong C#.

Nội dung

Để đọc hiểu bài này tốt nhất những bạn nên có kỹ năng và kiến thức cơ bản về những phần :

Trong bài học này, chúng ta sẽ cùng tìm hiểu các vấn đề:

  • Khái niệm kế thừa.
  • Khai báo và sử dụng kế thừa.
  • Các vấn đề trong kế thừa.

Khái niệm kế thừa

Trong thực tế, kế thừa là việc thừa hưởng lại những gì mà người khác để lại. Ví dụ: con kế thừa tài sản của cha,. . .

Trong lập trình cũng vậy, kế thừa trong lập trình là cách 1 lớp có thể thừa hưởng lại những thuộc tính, phương thức từ 1 lớp khác và sử dụng chúng như là của bản thân mình.

Một định nghĩa trừu tượng hơn về kế thừa: là một đặc điểm của ngôn ngữ hướng đối tượng dùng để biểu diễn mối quan hệ đặc biệt hoá – tổng quát hoá giữa các lớp.

Ví dụ: Giả sử ta có lớp TamGiac chứa thông tin toạ độ của 3 điểm A, B, C. Ta biết rằng tam giác cân là 1 trường hợp đặc biệt của tam giác (ngược lại tam giác là trường hợp tổng quát của tam giác cân).

Từ đó ta hoàn toàn có thể cho lớp TamGiacCan kế thừa lại lớp TamGiac để hoàn toàn có thể sử dụng lại những thông tin như tọa độ 3 điểm A, B, C mà không cần phải khai báo .
Ngoài ra, ta hoàn toàn có thể xét những lớp với những đặc thù tương tự như nhau, sau đó rút trích những thành phần chung và tạo thành 1 lớp. Cuối cùng cho những lớp kế thừa từ lớp cha đó để sử dụng lại thông tin mà không cần khai báo .
Dĩ nhiên là việc kế thừa không nên triển khai 1 cách lung tung, lạm dụng .

Ưu điểm của kế thừa

  • Cho phép xây dựng 1 lớp mới từ lớp đã có.
    •  Lớp mới gọi là lớp con ( subclass ) hay lớp dẫn xuất ( derived class ).
    •  Lớp đã có gọi là lớp cha ( superclass ) hay lớp cơ sở ( base class ).
  • Cho phép chia sẽ các thông tin chung nhằm tái sử dụng và đồng thời giúp ta dễ dàng nâng cấp, dễ dàng bảo trì.
  • Định nghĩa sự tương thích giữa các lớp, nhờ đó ta có thể chuyển kiểu tự động (sẽ được trình bày trong bài ĐA HÌNH TRONG LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG).

Khai báo và sử dụng kế thừa

Cú pháp

class :

{
}

Trong đó :

  • class

    là từ khoá để khai báo lớp.

  • là tên do người dùng đặt và tuân theo các quy tắc đặt tên (quy tắc đặt tên đã trình bày trong bài BIẾN TRONG C#).

  • là tên lớp mà ta muốn kế thừa các đặc tính của nó.

Sử dụng

class Animal
    {
        protected double Weight;
        protected double Height;
        protected static int Legs;

        public void Info()
        {
            Console.WriteLine(" Weight: " + Weight + " Height: " + Height + " Legs: " + Legs);
        }
    }


class Cat : Animal
    {
        public Cat()
        {
            /*
                Lớp Cat kế thừa lớp Animal
                mà các thuộc tính Weight, Height, Legs có phạm vi là protected nên được phép kế thừa
                Từ đó lớp Cat có thể sử dụng mà không cần phải khai báo

             */
            Weight = 500;
            Height = 20;
            Legs = 2;
        }
    }

Trong hàm main ta thử gọi phương thức Info xem có được không nhé:

Cat BlackCat = new Cat();

            /* Lớp Cat kế thừa phương thức Info từ lớp Animal nên đối tượng thuộc lớp Cat có thể gọi phương thức Info() */

            BlackCat.Info();

Kết quả khi chạy chương trình trên :

Kế thừa trong Lập trình hướng đối tượng

Bạn hoàn toàn có thể thấy nhờ kế thừa mà lớp con trở nên ngắn gọn hơn rất nhiều .

Lưu ý:

Trong C#, không hỗ trợ đa kế thừa (1 lớp kế thừa từ nhiều lớp) những lại hỗ trợ thực thi nhiều interface (khái niệm về interface sẽ được trình bày trong bài INTERFACE TRONG C#).

Các thành phần của lớp cha có được kế thừa xuống lớp con hay không là do khoanh vùng phạm vi truy vấn của thành phần đó là gì .

  •  Thành phần có phạm vi là private thì không được kế thừa.
  •  Thành phần có phạm vi là protected, public thì được phép kế thừa.

Phương thức khởi tạo và phương pháp hủy bỏ không được kế thừa .

Các vấn đề trong kế thừa

Vấn đề về phương thức khởi tạo, phương thức huỷ bỏ

Phương thức khởi tạo mặc định của lớp cha luôn luôn được gọi mỗi khi có 1 đối tượng thuộc lớp con khởi tạo. Và được gọi trước phương thức khởi tạo của lớp con.

Nếu như lớp cha có phương pháp khởi tạo có tham số thì yên cầu lớp con phải có phương pháp khởi tạo tương ứng và thực thi gọi phương pháp khởi tạo của lớp cha trải qua từ khóa base .

Ví dụ: Giả sử lớp Animal có thêm 1 constructor có tham số như sau:

class Animal
    {
        public Animal(double w, double h, int l)
        {
            Weight = w;
            Height = h;
            Legs = l;
        }
    }

Khi đó lớp con kế thừa từ lớp Animal phải có constructor có các tham số tương ứng:

class Cat : Animal
    {
        /*
            Cách gọi constructor của lớp cha thông qua từ khoá base
         */

        public Cat()
        {         
            Weight = 500;
            Height = 20;
            Legs = 2;
        }


        /*
            Cách gọi constructor của lớp cha thông qua từ khoá base
         */

        public Cat(double w, double h, int l) : base(w, h, l)
        {
          

        }
    }

Qua ví dụ trên bạn dễ dàng thấy được cú pháp để gọi constructor của lớp cha như sau:

public () : base()

{
}

Trong đó :

  • là tên lớp con (lớp dẫn xuất).

  • là danh sách tham số của constructor của lớp con.

  • base

    là từ khoá để gọi đến constructor của lớp cha.

  • là danh sách tham số tương ứng với constructor của lớp cha.

Khi đối tượng người tiêu dùng của lớp con bị hủy thì phương pháp hủy bỏ của nó sẽ được gọi trước sau đó mới gọi phương pháp hủy bỏ của lớp cha để hủy những gì lớp con không hủy được .

Vấn đề hàm trùng tên và cách gọi phương thức của lớp cha

Kế thừa trong Lập trình hướng đối tượng

Xét lại ví dụ phía trên. Giả sử lớp Animal có phương phức tên Info(). Lớp Cat kế thừa lớp Animal nên cũng sẽ nhận được phương thức này.

Bây giờ trong lớp Cat ta cũng định nghĩa 1 phương thức tên Info(), có kiểu trả về là void và không có tham số truyền vào. Vậy câu lệnh sau sẽ gọi phương thức Info() nào?

Cat BlackCat = new Cat();

BlackCat.Info();

Câu trả lời là C# sẽ gọi phương thức Info() của lớp Cat định nghĩa. Đồng thời cũng đưa ra 1 cảnh báo khi biên dịch.

Trong C# có hỗ trợ từ khoá new nhằm đánh dấu đây là 1 hàm mới và hàm kế thừa từ lớp cha sẽ bị che đi khiến bên ngoài không thể gọi được.

Cụ thể bạn sẽ thêm từ khóa new vào trước khai báo hàm Info ( ) trong lớp Cat .

public new void Info()

{
}

Khi đó hàm Info() của lớp cha sẽ bị che giấu đi. Và mọi đối tượng bên ngoài chỉ gọi được hàm Info() của lớp Cat.

Từ khoá này chỉ làm tường minh khai báo của hàm Info() chứ về kết quả khi chạy chương trình sẽ không có thay đổi.

Đến đây 1 câu hỏi nữa được đặt ra: Vậy có cách nào gọi hàm Info() của lớp cha được nữa không?

Câu vấn đáp là có nhưng chỉ hoàn toàn có thể gọi trong nội bộ của lớp Cat mà thôi .
Bạn hoàn toàn có thể sử dụng từ khóa base để đại diện thay mặt cho lớp cha và gọi đến những thành phần của lớp cha .

Ví dụ: gọi hàm Info() của lớp cha:   

  /* Từ khoá new chỉ định đây là 1 hàm Info mới của lớp Cat */

        public new void Info()
        {

            Console.WriteLine(" Info of Cat: ");
            base.Info(); // gọi đến hàm Info() của lớp cha

        }

Kết quả khi gọi hàm Info() của lớp Cat là:

Kế thừa trong Lập trình hướng đối tượng

Vấn đề cấp phát vùng nhớ cho đối tượng

Bình thường nếu như 1 đối tượng người dùng kiểu Animal không hề khởi tạo vùng nhớ có kiểu Cat được .

Animal cat = new Cat();

Câu lệnh này sẽ báo lỗi : “ không hề chuyển từ kiểu Cat sang kiểu Animal ” .
Nhưng nếu như 2 lớp này có quan hệ kế thừa thì điều này trọn vẹn được .
Tính chất này được phát biểu như sau :

Một đối tượng thuộc lớp cha có thể tham chiếu đến vùng nhớ của đối tượng thuộc lớp con nhưng ngược lại thì không”.

Có nghĩa là nếu lớp Cat kế thừa từ lớp Animal thì câu lệnh Animal cat = new Cat(); hoàn toàn đúng nhưng ngược lại Cat cat = new Animal (); sẽ báo lỗi.

Bạn cần quan tâm điều này. Vì muốn biểu lộ tính đa hình trong lập trình ta phải sử dụng đặc thù này .

Kết luận

Nội dung bài này giúp những bạn nắm được :

  • Khái niệm kế thừa.
  • Khai báo và sử dụng kế thừa.
  • Các vấn đề trong kế thừa.

Bài sau chúng ta sẽ tìm hiểu về ĐA HÌNH TRONG LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG .

Cảm ơn các bạn đã theo dõi bài viết. Hãy để lại bình luận hoặc góp ý của mình để phát triển bài viết tốt hơn. Đừng quên “Luyện tập – Thử thách – Không ngại khó”.

Thảo luận

Nếu bạn có bất kể khó khăn vất vả hay vướng mắc gì về khóa học, đừng ngần ngại đặt câu hỏi trong phần bên dưới hoặc trong mục HỎI và ĐÁP trên thư viện Howkteam. com để nhận được sự tương hỗ từ hội đồng .