VieTopik
Thư việnLuyện thiGóc học tậpĐánh dấu
Tải app
  • Thư viện
  • Luyện thi
  • Góc học tập
  • Đánh dấu
OOP và thiết kế

Bài 1/1

Kế thừa

5 phút đọc

Nội dung bài

  1. 1.Khái niệm
  2. 2.Ví dụ
  3. 3.Thử ngay
  4. 4.Lỗi hay gặp
  5. 5.Tóm tắt

Cửa hàng bán sách giấy và ebook. Cả hai đều có tên, có giá, có cùng cách hiển thị. Viết hai class riêng thì phần chung bị lặp lại, sửa một chỗ lại phải nhớ sửa chỗ kia. Kế thừa giải quyết đúng việc này.

Khái niệm

🧬 Kế thừa (inheritance): class con nhận lại property và method của class cha, rồi thêm phần riêng của mình.

👪 Class cha, class con (base class, derived class): class được kế thừa là class cha, class kế thừa nó là class con, khai báo bằng class Con : Cha.

Kế thừa chỉ đúng khi class con là một loại của class cha. Sách giấy là một loại sản phẩm, nên PhysicalProduct : Product hợp lý.

Ví dụ

var book = new PhysicalProduct("Sách C#", 150000, 800);
Console.WriteLine(book.Describe());
Console.WriteLine(book.ShippingFee());

class Product
{
    public string Name { get; }
    public decimal Price { get; }

    public Product(string name, decimal price)
    {
        Name = name;
        Price = price;
    }

    public string Describe()
    {
        return $"{Name} - {Price}đ";
    }
}

class PhysicalProduct : Product
{
    public int WeightGram { get; }

    public PhysicalProduct(
        string name, decimal price, int weightGram)
        : base(name, price)
    {
        WeightGram = weightGram;
    }

    public decimal ShippingFee()
    {
        return WeightGram * 10;
    }
}
  • book dùng được Name, Price, Describe() dù PhysicalProduct không khai báo chúng. Tất cả nhận lại từ Product.
  • WeightGram và ShippingFee() là phần riêng, chỉ class con có.
  • Constructor không được kế thừa. : base(name, price) gọi constructor của Product để gán Name và Price, rồi class con gán tiếp WeightGram.
  • Một class chỉ kế thừa được một class cha.

Thử ngay

Chép ví dụ trên vào Program.cs. Thay ba dòng đầu bằng các lệnh gọi dưới đây, rồi thêm class DigitalProduct vào cuối file:

var ebook = new DigitalProduct(
    "Ebook C#", 90000, "https://shop.vn/ebook");

Console.WriteLine(ebook.Describe());
Console.WriteLine(ebook.DownloadUrl);

class DigitalProduct : Product
{
    public string DownloadUrl { get; }

    public DigitalProduct(
        string name, decimal price, string downloadUrl)
        : base(name, price)
    {
        DownloadUrl = downloadUrl;
    }
}

Đoán trước khi chạy: DigitalProduct không hề khai báo Describe(). Dòng ebook.Describe() có chạy được không, và in ra gì?

Xem kết quả
Ebook C# - 90000đ
https://shop.vn/ebook

Chạy được. DigitalProduct kế thừa Describe() từ Product, nên phần chung chỉ viết một lần ở class cha.

Lỗi hay gặp

Quên gọi base(...). Class cha không có constructor rỗng thì compiler không biết tạo phần cha bằng cách nào.

// SAI — lỗi compile: thiếu base(name, price)
class GiftCard : Product
{
    public GiftCard(string name, decimal price)
    {
    }
}
// ĐÚNG
class GiftCard : Product
{
    public GiftCard(string name, decimal price)
        : base(name, price)
    {
    }
}

Kế thừa chỉ để dùng lại code. Khách hàng không phải là một địa chỉ, nên Customer : Address là sai, dù nó giúp Customer có sẵn Street.

// SAI — khách hàng không "là một" địa chỉ
class Customer : Address
{
    public string Name { get; set; } = "";
}

class Address
{
    public string Street { get; set; } = "";
}
// ĐÚNG — khách hàng "có một" địa chỉ
class Customer
{
    public string Name { get; set; } = "";
    public Address Address { get; set; }
        = new Address();
}

Tóm tắt

  • class Con : Cha: class con nhận lại property và method của class cha, rồi thêm phần riêng.
  • Constructor không được kế thừa, class con gọi constructor cha bằng : base(...).
  • Một class chỉ có một class cha.
  • Chỉ kế thừa khi con là một loại của cha.

Tự kiểm tra

0/3 câu
Câu 1

Class Employee có method GetInfo(). Class Manager : Employee không khai báo gì thêm. Gọi new Manager(...).GetInfo() thì sao?

Câu 2

Class Vehicle chỉ có constructor Vehicle(string plate). Class Truck : Vehicle viết constructor Truck(string plate) { } mà không có : base(plate). Chuyện gì xảy ra?

Câu 3

Trường hợp nào dùng kế thừa là hợp lý?