Bài 1/1
Kế thừa
5 phút đọc
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;
}
}bookdùng đượcName,Price,Describe()dùPhysicalProductkhông khai báo chúng. Tất cả nhận lại từProduct.WeightGramvàShippingFee()là phần riêng, chỉ class con có.- Constructor không được kế thừa.
: base(name, price)gọi constructor củaProductđể gánNamevàPrice, rồi class con gán tiếpWeightGram. - 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/ebookChạ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âuClass Employee có method GetInfo(). Class Manager : Employee không khai báo gì thêm. Gọi new Manager(...).GetInfo() thì sao?
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?
Trường hợp nào dùng kế thừa là hợp lý?