Đa hình
Nội dung bài · 5 mục
- 1.Khái niệm
- 2.Ví dụ
- 3.Thử ngay
- 4.Lỗi hay gặp
- 5.Tóm tắt
Giỏ hàng có sách giấy tính phí ship theo cân nặng và ebook miễn phí ship. Viết if kiểm tra từng loại thì mỗi lần thêm loại hàng
mới lại phải sửa giỏ hàng. Với đa hình, mỗi loại tự biết cách tính của mình.
Khái niệm
🎭 Đa hình (polymorphism): cùng một lời gọi method, mỗi class con chạy cách làm riêng của nó.
🔧 virtual và override: virtual ở class cha cho phép class con viết lại method, override ở class con là bản viết lại đó.
Ví dụ
var cart = new List<Product>
{
new PhysicalProduct
{ Name = "Sách", WeightGram = 800 },
new DigitalProduct { Name = "Ebook C#" },
};
foreach (Product item in cart)
{
Console.WriteLine(
$"{item.Name}: {item.ShippingFee()}");
}
class Product
{
public string Name { get; set; } = "";
public virtual decimal ShippingFee() => 30000m;
}
class PhysicalProduct : Product
{
public int WeightGram { get; set; }
public override decimal ShippingFee() =>
WeightGram * 10m;
}
class DigitalProduct : Product
{
public override decimal ShippingFee() => 0m;
}Sách: 8000
Ebook C#: 0- Để code ngắn, bài này dùng
{ get; set; }và object initializernew ... { Name = ... }đã gặp ở bài Value type và reference type. ShippingFee()nằm ởProductvà được đánh dấuvirtual.List<Product>chứa được cảPhysicalProductvàDigitalProduct, vì cả hai đều làProduct.- Vòng lặp chỉ gọi
item.ShippingFee(), không cần biết món hàng thuộc loại nào. - C# chạy bản
overridecủa object thật, không phải bản củaProduct. - Thêm loại hàng mới chỉ cần viết class mới có
override. Vòng lặp không đổi.
Thử ngay
Chép ba class ở ví dụ trên, thay các dòng đầu bằng:
Product item = new DigitalProduct { Name = "Ebook" };
Console.WriteLine(item.ShippingFee());
Product other = new Product { Name = "Quà tặng" };
Console.WriteLine(other.ShippingFee());Đoán trước khi chạy: biến item có kiểu Product. Dòng đầu in 30000
hay 0?
Xem kết quả
0
30000In 0. Kiểu của biến là Product, nhưng object thật là DigitalProduct, và
C# chạy bản override của object thật. Còn other là Product thường nên
chạy bản gốc, in 30000.
Lỗi hay gặp
Quên virtual ở class cha. Method không có virtual thì class con không
override được.
// SAI — lỗi compile: Fee không phải virtual
class Item
{
public decimal Fee() => 30000m;
}
class Gift : Item
{
public override decimal Fee() => 0m;
}// ĐÚNG
class Item
{
public virtual decimal Fee() => 30000m;
}
class Gift : Item
{
public override decimal Fee() => 0m;
}Quên override ở class con. Code vẫn build, chỉ có cảnh báo. Nhưng gọi
qua biến kiểu cha thì chạy bản của cha.
// SAI — thiếu override, in ra 30000
Item gift = new Gift();
Console.WriteLine(gift.Fee());
class Item
{
public virtual decimal Fee() => 30000m;
}
class Gift : Item
{
public decimal Fee() => 0m;
}// ĐÚNG — có override, in ra 0
Item gift = new Gift();
Console.WriteLine(gift.Fee());
class Item
{
public virtual decimal Fee() => 30000m;
}
class Gift : Item
{
public override decimal Fee() => 0m;
}Tóm tắt
- Đa hình: cùng một lời gọi, mỗi class con chạy cách làm riêng.
- Class cha đánh dấu
virtual, class con viết lại bằngoverride. - Biến kiểu cha chứa được object của class con, và C# chạy bản của object thật.
- Thêm loại mới chỉ cần thêm class, không sửa chỗ gọi.
Tự kiểm tra
0/3 câuclass Animal { public virtual string Sound() => "..."; } class Dog : Animal { public override string Sound() => "Gâu"; } Animal a = new Dog(); Console.WriteLine(a.Sound()); In ra gì?
Class cha có method public decimal Discount(). Class con viết public override decimal Discount(). Chuyện gì xảy ra?
Cửa hàng thêm loại hàng mới là "voucher" với phí ship riêng. Nếu đã dùng đa hình, cần làm gì?