Hướng dẫn入门 về Đa hình (Polymorphism) trong C

Xin chào các bạn học lập trình! Hôm nay, chúng ta sẽ cùng tìm hiểu một trong những khái niệm thú vị nhất trong lập trình hướng đối tượng: Đa hình (Polymorphism). Đừng để từ ngữ lớn này làm bạn sợ hãi - đến cuối bài hướng dẫn này, bạn sẽ sử dụng đa hình như một chuyên gia!

C# - Polymorphism

Đa hình là gì?

Trước khi chúng ta bắt đầu, hãy phân tích từ ngữ này. "Poly" có nghĩa là nhiều, và "morph" có nghĩa là hình thức. Vậy, đa hình là tất cả về việc có nhiều hình thức. Trong lập trình, nó là khả năng của các đối tượng có thể lấy nhiều hình thức và hành xử khác nhau dựa trên ngữ cảnh.

Hãy tưởng tượng bạn là một người có khả năng变身 (thật tuyệt vời phải không?). Bạn có thể là con người, con mèo, hoặc thậm chí là con rồng! Đó chính xác là điều mà đa hình cho phép mã của chúng ta làm - lấy nhiều hình thức khi cần thiết.

Trong C#, chúng ta có hai loại đa hình chính:

  1. Đa hình tĩnh (còn gọi là Đa hình theo thời gian biên dịch)
  2. Đa hình động (còn gọi là Đa hình theo thời gian chạy)

Hãy cùng khám phá từng loại này chi tiết.

Đa hình tĩnh

Đa hình tĩnh xảy ra khi bộ biên dịch biết phương thức nào cần gọi tại thời gian biên dịch. Nó giống như việc quyết định mặc gì trước khi ra khỏi nhà - bạn biết trước!

Tải trọng hàm (Function Overloading)

Đa hình tĩnh phổ biến nhất là tải trọng hàm. Đây là khi bạn có nhiều phương thức với cùng tên nhưng các tham số khác nhau.

Hãy xem một ví dụ:

public class Calculator
{
public int Add(int a, int b)
{
return a + b;
}

public double Add(double a, double b)
{
return a + b;
}

public string Add(string a, string b)
{
return a + b;
}
}

Trong ví dụ này, chúng ta có ba phương thức Add:

  1. Một phương thức cộng hai số nguyên
  2. Một phương thức cộng hai số thực
  3. Một phương thức nối hai chuỗi

Bây giờ, hãy sử dụng Calculator của chúng ta:

Calculator calc = new Calculator();

int sum1 = calc.Add(5, 3);            // Sử dụng phiên bản số nguyên
double sum2 = calc.Add(3.14, 2.86);   // Sử dụng phiên bản số thực
string sum3 = calc.Add("Hello, ", "World!"); // Sử dụng phiên bản chuỗi

Console.WriteLine(sum1);  // Output: 8
Console.WriteLine(sum2);  // Output: 6
Console.WriteLine(sum3);  // Output: Hello, World!

Bộ biên dịch biết phương thức Add nào cần gọi dựa trên các loại đối số chúng ta truyền. Nó giống như có một cây kéo đa năng - một công cụ, nhiều cách sử dụng!

Đa hình động

Đa hình động là khi quyết định về phương thức nào cần gọi được thực hiện tại thời gian chạy. Nó giống như việc импровизировать на сцене - bạn quyết định làm gì trong từng khoảnh khắc!

Chìa khóa của đa hình động là việc sử dụng các từ khóa virtualoverride. Hãy xem một ví dụ:

public class Animal
{
public virtual void MakeSound()
{
Console.WriteLine("The animal makes a sound");
}
}

public class Dog : Animal
{
public override void MakeSound()
{
Console.WriteLine("The dog barks: Woof! Woof!");
}
}

public class Cat : Animal
{
public override void MakeSound()
{
Console.WriteLine("The cat meows: Meow! Meow!");
}
}

Trong ví dụ này, chúng ta có một lớp cơ bản Animal với phương thức MakeSound ảo. Các lớp DogCat kế thừa từ Animal và ghi đè phương thức MakeSound.

Bây giờ, hãy xem đa hình động trong hành động:

Animal myAnimal = new Animal();
Animal myDog = new Dog();
Animal myCat = new Cat();

myAnimal.MakeSound();  // Output: The animal makes a sound
myDog.MakeSound();     // Output: The dog barks: Woof! Woof!
myCat.MakeSound();     // Output: The cat meows: Meow! Meow!

myDogmyCat được khai báo là loại Animal, chúng vẫn sử dụng phương thức MakeSound của riêng mình. Đây là phép màu của đa hình động!

Sức mạnh của Đa hình

Đa hình cho phép chúng ta viết mã linh hoạt và dễ tái sử dụng hơn. Hãy tưởng tượng bạn đang tạo một trò chơi với các loại nhân vật khác nhau. Mỗi nhân vật có thể di chuyển khác nhau:

public class Character
{
public virtual void Move()
{
Console.WriteLine("The character moves.");
}
}

public class Warrior : Character
{
public override void Move()
{
Console.WriteLine("The warrior charges forward!");
}
}

public class Mage : Character
{
public override void Move()
{
Console.WriteLine("The mage teleports.");
}
}

public class Rogue : Character
{
public override void Move()
{
Console.WriteLine("The rogue sneaks silently.");
}
}

Bây giờ, chúng ta có thể có một danh sách các nhân vật và làm cho chúng đều di chuyển:

List<Character> characters = new List<Character>
{
new Warrior(),
new Mage(),
new Rogue()
};

foreach (var character in characters)
{
character.Move();
}

// Output:
// The warrior charges forward!
// The mage teleports.
// The rogue sneaks silently.

Đây là vẻ đẹp của đa hình - chúng ta có thể coi tất cả các nhân vật này là các đối tượng Character, nhưng chúng hành xử theo cách riêng của mình.

Tóm tắt các phương thức Đa hình

Dưới đây là bảng tham khảo nhanh các phương thức đa hình chúng ta đã covered:

Phương thức Loại Mô tả
Tải trọng hàm Tĩnh Nhiều phương thức với cùng tên nhưng các tham số khác nhau
Virtual/Override Động Lớp cơ bản định nghĩa phương thức ảo, các lớp con ghi đè chúng

Kết luận

Chúc mừng! Bạn đã刚刚 bước vào thế giới của đa hình. Nhớ rằng, như bất kỳ kỹ năng mới nào, việc thành thạo đa hình đòi hỏi sự thực hành. Đừng nản lòng nếu nó không ngay lập tức hiểu rõ - tiếp tục mã hóa, tiếp tục thử nghiệm, và sớm bạn sẽ định hình các chương trình của mình như một người lập trình thực sự có khả năng变身!

Khi kết thúc, đây là một câu đùa lập trình cho bạn: Tại sao các lập trình viên thích chế độ tối? Vì ánh sáng thu hút sâu bọ!

Chúc các bạn may mắn, những nhà vô địch đa hình tương lai!

Credits: Image by storyset