VieTopik
Tiếng HànTiếng AnhIT
  • Góc học tập
Tải app
  • Thư viện
  • Luyện thi
  • Cẩm nang
  • Góc học tập
OOP và thiết kếBốn trụ cột OOP
Bài 3/12
5 phút

Đa hình

Nội dung bài · 5 mục
  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

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 initializer new ... { Name = ... } đã gặp ở bài Value type và reference type.
  • ShippingFee() nằm ở Product và được đánh dấu virtual.
  • List<Product> chứa được cả PhysicalProduct và 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 override của object thật, không phải bản của Product.
  • 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.
PhysicalProduct DigitalProduct item.ShippingFee() Object thật là gì? WeightGram * 10m 0m
Cùng một lời gọi, C# chọn bản override theo object thật

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
30000

In 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ằng override.
  • 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âu
Câu 1

class 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ì?

Câu 2

Class cha có method public decimal Discount(). Class con viết public override decimal Discount(). Chuyện gì xảy ra?

Câu 3

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ì?

Kế thừaAbstract class

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