Tính đa hình trong C#
Nguyễn Dương 07-06-20241. TÍNH ĐA HÌNH LÀ GÌ
Đa hình (polymorphism) hiểu theo cách thông thường là đa dạng, phong phú, nhiều kiểu, nhiều hình thái.
Polymorphism được cấu tạo từ 2 từ Hy Lạp: poly và morphs. Trong đó poly có nghĩa là nhiều và morphs có nghĩa là hình thái.
Trong lập trình C#, tính đa hình được hiểu là hiện tượng các đối tượng thuộc các lớp khác nhau, thực hiện cùng một hành động bằng các cách khác nhau.
Ví dụ ta có 3 loài vật là chó, lợn và mèo. 3 loài đều có tiếng kêu nhưng mỗi loài lại có tiếng kêu riêng, chó thì sủa "gâu gâu", lợn thì kêu "éc éc", mèo thì kêu "meo meo". Cùng là hành động kêu nhưng mỗi loài lại thực hiện theo các cách khác nhau.
Ví dụ ta có 3 loài vật là chó, lợn và mèo. 3 loài đều có tiếng kêu nhưng mỗi loài lại có tiếng kêu riêng, chó thì sủa "gâu gâu", lợn thì kêu "éc éc", mèo thì kêu "meo meo". Cùng là hành động kêu nhưng mỗi loài lại thực hiện theo các cách khác nhau.
Lưu ý: Các lớp phải là con của cùng 1 lớp cha.
2. SỬ DỤNG TÍNH ĐA HÌNH
- Tính đa hình chỉ được thể hiện khi đã ghi đè lên phương thức của lớp cha.
- Chỉ có thể ghi đè lên phương thức virtual hoặc abstract
Cách khai báo:
- Để khai báo 1 phương thức ảo bạn sử dụng từ khóa virtual.
- Để ghi đè lên phương thức của lớp cha, bạn sử dụng từ khóa override.
Ví dụ: Mình tạo ra 1 lớp Animal và 2 lớp con là Cat và Dog. Các lớp đều có hàm Speak.
namespace da_hinh { class Animal { public virtual void Speak() { Console.WriteLine("Dong vat keu ......"); } } class Cat : Animal { public override void Speak() { Console.WriteLine("Meo keu meo meo"); } } class Dog : Animal { public void Speak() { Console.WriteLine("Cho keu gau gau"); } } class Program { static void Main(string[] args) { Animal Cat1 = new Cat(); Cat1.Speak(); Animal Dog1 = new Dog(); Dog1.Speak(); Console.ReadLine(); } } }
Ở đây mình không khởi tạo Cat Cat1 = new Cat mà là Animal Cat = new Cat.
Hàm Speak ở lớp Animal mình có khai báo virtual, hàm Speak của lớp Cat có khai báo override còn ở lớp Dog thì không.
Kết quả
Hàm Speak của lớp Dog không có override nên chương trình chạy hàm của lớp cha.
Đồng nghĩa với việc nếu mình không khai báo virtual ở lớp cha, không có override ở lớp con thì chương trình sẽ in ra màn hình 2 dòng Dong vat keu ......
Phần định nghĩa bên trong thân hàm chỉ là hình thức, thay vì như vậy bạn có thể khai báo lớp trừu tượng cho lớp Animal, khai báo hàm trừu tượng cho hàm Speak trong lớp Animal và không cần định nghĩa bên trong hàm.
Để khai báo 1 lớp trừu tượng hoặc 1 phương thức trừu tượng ta dùng từ khóa abstract
Kết quả này cũng giống như khi mình khai báo hàm virtual.
Kết quả
Hàm Speak của lớp Dog không có override nên chương trình chạy hàm của lớp cha.
Đồng nghĩa với việc nếu mình không khai báo virtual ở lớp cha, không có override ở lớp con thì chương trình sẽ in ra màn hình 2 dòng Dong vat keu ......
3. LỚP TRỪU TƯỢNG
Tiếp tục xét ví dụ trên, các bạn có thấy, tại lớp cha Animal, việc gì ta phải mất công chạy lệnh Console.WriteLine trong hàm Speak. Vì đến lớp con, hàm đó lại bị ghi đè bằng hàm riêng của lớp con. Bạn có thể bỏ trống phần nội dung thân hàm Speak, kết quả vẫn ra tương tự.Phần định nghĩa bên trong thân hàm chỉ là hình thức, thay vì như vậy bạn có thể khai báo lớp trừu tượng cho lớp Animal, khai báo hàm trừu tượng cho hàm Speak trong lớp Animal và không cần định nghĩa bên trong hàm.
Để khai báo 1 lớp trừu tượng hoặc 1 phương thức trừu tượng ta dùng từ khóa abstract
namespace da_hinh
{
abstract class Animal
{
public abstract void Speak();
}
class Cat : Animal
{
public override void Speak()
{
Console.WriteLine("Meo keu meo meo");
}
}
class Dog : Animal
{
public override void Speak()
{
Console.WriteLine("Cho keu gau gau");
}
}
class Program
{
static void Main(string[] args)
{
Animal Cat1 = new Cat();
Cat1.Speak();
Animal Dog1 = new Dog();
Dog1.Speak();
Console.ReadLine();
}
}
}
Kết quả
Kết quả này cũng giống như khi mình khai báo hàm virtual.
Lưu ý:
Khi kế thừa 1 lớp trừu tượng bạn bắt buộc phải override tất cả các phương thức trừu tượng nhằm đảm bảo tính hợp lệ cho chương trình.
Khi kế thừa 1 lớp trừu tượng bạn bắt buộc phải override tất cả các phương thức trừu tượng nhằm đảm bảo tính hợp lệ cho chương trình.
Bài viết liên quan
Interface trong C#
Tính đa hình trong C#
Tính kế thừa trong C#
this và static trong C#
Các loại phạm vi truy cập trong C#
Hàm khởi tạo và hàm hủy