Đa hình (Polymorphism) là một khái niệm quan trọng trong lập trình hướng đối tượng (OOP). Từ "polymorphism" xuất phát từ tiếng Hy Lạp, trong đó "poly" có nghĩa là "nhiều" và "morph" có nghĩa là "hình dạng". Trong lập trình, đa hình cho phép các đối tượng thuộc các lớp khác nhau có thể được xử lý thông qua cùng một giao diện. Điều này mang lại sự linh hoạt và khả năng mở rộng cho mã nguồn, giúp giảm thiểu sự phụ thuộc và tăng tính tái sử dụng.
Các Loại Đa Hình trong Python
Trong Python, có nhiều cách để thực hiện tính đa hình, bao gồm:
- Đa Hình Thông Qua Kế Thừa (Inheritance)
- Đa Hình Thông Qua Ghi Đè Phương Thức (Method Overriding)
- Đa Hình Thông Qua Nạp Chồng Phương Thức (Method Overloading)
- Đa Hình Thông Qua Nạp Chồng Toán Tử (Operator Overloading)
- Đa Hình Thông Qua Duck Typing
Đa Hình Thông Qua Kế Thừa (Inheritance)
Kế thừa là một cơ chế trong OOP cho phép một lớp con kế thừa các thuộc tính và phương thức từ một lớp cha. Điều này cho phép các lớp con có thể sử dụng lại mã nguồn của lớp cha và cũng có thể ghi đè các phương thức của lớp cha để cung cấp các hành vi cụ thể.
Ví Dụ
python
class Animal:
def sound(self):
raise NotImplementedError("Subclass must implement abstract method")
class Dog(Animal):
def sound(self):
return "Woof"
class Cat(Animal):
def sound(self):
return "Meow"
# Sử dụng đa hình
def make_sound(animal):
print(animal.sound())
dog = Dog()
cat = Cat()
make_sound(dog) # Output: Woof
make_sound(cat) # Output: Meow
Trong ví dụ trên, lớp Animal
là lớp cha với phương thức sound
được định nghĩa là một phương thức trừu tượng. Các lớp con Dog
và Cat
kế thừa từ Animal
và ghi đè phương thức sound
để cung cấp các hành vi cụ thể.
Đa Hình Thông Qua Ghi Đè Phương Thức (Method Overriding)
Ghi đè phương thức là một kỹ thuật cho phép lớp con cung cấp một triển khai cụ thể cho một phương thức đã được định nghĩa trong lớp cha. Điều này cho phép lớp con thay đổi hành vi của phương thức kế thừa từ lớp cha.
Ví Dụ
python
class Bird:
def intro(self):
print("There are many types of birds.")
def flight(self):
print("Most of the birds can fly but some cannot.")
class Sparrow(Bird):
def flight(self):
print("Sparrows can fly.")
class Ostrich(Bird):
def flight(self):
print("Ostriches cannot fly.")
obj_bird = Bird()
obj_spr = Sparrow()
obj_ost = Ostrich()
obj_bird.intro()
obj_bird.flight()
obj_spr.intro()
obj_spr.flight()
obj_ost.intro()
obj_ost.flight()
Kết Quả:
There are many types of birds.
Most of the birds can fly but some cannot.
There are many types of birds.
Sparrows can fly.
There are many types of birds.
Ostriches cannot fly.
Trong ví dụ trên, phương thức flight
được ghi đè trong các lớp con Sparrow
và Ostrich
để cung cấp các hành vi cụ thể cho từng loại chim.
Đa Hình Thông Qua Nạp Chồng Phương Thức (Method Overloading)
Nạp chồng phương thức là một kỹ thuật cho phép định nghĩa nhiều phương thức cùng tên trong cùng một lớp nhưng với các tham số khác nhau. Python không hỗ trợ nạp chồng phương thức theo cách truyền thống như các ngôn ngữ khác, nhưng có thể đạt được điều này bằng cách sử dụng các tham số mặc định hoặc *args.
Ví Dụ
python
class Math:
def add(self, a, b, c=0):
return a + b + c
math = Math()
print(math.add(2, 3)) # Output: 5
print(math.add(2, 3, 4)) # Output: 9
Trong ví dụ trên, phương thức add
có thể được gọi với hai hoặc ba tham số nhờ vào tham số mặc định c
.
Đa Hình Thông Qua Nạp Chồng Toán Tử (Operator Overloading)
Nạp chồng toán tử cho phép định nghĩa lại các toán tử để chúng có thể hoạt động với các đối tượng của lớp do người dùng định nghĩa. Điều này được thực hiện bằng cách định nghĩa các phương thức đặc biệt trong lớp.
Ví Dụ
python
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def __add__(self, other):
return Vector(self.x + other.x, self.y + other.y)
def __str__(self):
return f"Vector({self.x}, {self.y})"
v1 = Vector(2, 3)
v2 = Vector(4, 5)
v3 = v1 + v2
print(v3) # Output: Vector(6, 8)
Trong ví dụ trên, toán tử +
được nạp chồng để có thể cộng hai đối tượng Vector
.
Đa Hình Thông Qua Duck Typing
Duck typing là một khái niệm trong lập trình động, trong đó kiểu của một đối tượng được xác định bởi các phương thức và thuộc tính mà nó có, chứ không phải bởi lớp mà nó thuộc về. Nếu một đối tượng có các phương thức và thuộc tính cần thiết, nó có thể được sử dụng thay cho bất kỳ đối tượng nào khác có cùng các phương thức và thuộc tính đó.
Ví Dụ
python
class Dog:
def speak(self):
return "Woof woof"
class Cat:
def speak(self):
return "Meow meow"
class Animal:
def make_sound(self, animal):
print(animal.speak())
animal = Animal()
dog = Dog()
cat = Cat()
animal.make_sound(dog) # Output: Woof woof
animal.make_sound(cat) # Output: Meow meow
Trong ví dụ trên, đối tượng animal
có thể gọi phương thức speak
trên cả đối tượng dog
và cat
mà không cần biết chúng thuộc lớp nào, miễn là chúng có phương thức speak
.
Kết Luận
Tính đa hình là một khái niệm quan trọng trong lập trình hướng đối tượng, giúp mã nguồn trở nên linh hoạt và dễ bảo trì hơn. Python cung cấp nhiều cách để thực hiện tính đa hình, bao gồm kế thừa, ghi đè phương thức, nạp chồng phương thức, nạp chồng toán tử, và duck typing. Hiểu rõ và áp dụng đúng các kỹ thuật này sẽ giúp bạn viết mã Python hiệu quả và dễ bảo trì hơn.
Hy vọng bài viết này đã giúp bạn hiểu rõ hơn về tính đa hình trong Python và cách sử dụng các phương pháp khác nhau để đạt được mục tiêu của bạn.