Python - Polymorphism: Hướng Dẫn Cho Người Mới Bắt Đầu

Xin chào các bạn, các maestro Python tương lai! Hôm nay, chúng ta sẽ bắt đầu hành trình thú vị vào thế giới polymorphism trong Python. Đừng lo lắng nếu từ này có vẻ như một lời khai từ Harry Potter - đến cuối hướng dẫn này, bạn sẽ sử dụng polymorphism như một chuyên gia!

Python - Polymorphism

Polymorphism là gì trong Python?

Hãy tưởng tượng bạn có một chiếc cây đạo魔法 (hãy tin tưởng tôi, chúng ta sẽ đi hết Hogwarts ở đây). Chiếc cây này có thể biến hình thành các đối tượng khác nhau - đôi khi là một chiếc bút, đôi khi là một chiếc kiếm, và đôi khi là một chiếc đèn pin. Đó chính là điều gì polymorphism là trong lập trình!

Trong Python, polymorphism cho phép các đối tượng của các lớp khác nhau được xử lý như các đối tượng của một lớp cơ bản chung. Như có một chiếc cúp đa năng của mã - một giao diện, nhiều phần thực hiện.

Hãy xem một ví dụ đơn giản:

class Animal:
def speak(self):
pass

class Dog(Animal):
def speak(self):
return "Woof!"

class Cat(Animal):
def speak(self):
return "Meow!"

def animal_sound(animal):
print(animal.speak())

# Tạo các đối tượng
dog = Dog()
cat = Cat()

# Sử dụng polymorphism
animal_sound(dog)  # Output: Woof!
animal_sound(cat)  # Output: Meow!

Trong ví dụ này, cả DogCat đều được kế thừa từ lớp Animal. Hàm animal_sound không quan tâm đến loại động vật nó nhận được - nó chỉ gọi phương thức speak. Đây là polymorphism đang hoạt động!

Các Cách Thực Hiện Polymorphism trong Python

Python cung cấp một số cách để thực hiện polymorphism. Hãy khám phá chúng một:

Duck Typing trong Python

Duck typing là một khái niệm trong Python tập trung vào hành vi của một đối tượng thay vì kiểu của nó. Như câu trích dẫn nói: "Nếu nó trông như một vịt, bơi như một vịt, và gào như một vịt, thì nó có lẽ là một vịt."

Dưới đây là một ví dụ:

class Duck:
def quack(self):
print("Quack, quack!")

class Person:
def quack(self):
print("Tôi đang làm mời làm vịt!")

def make_it_quack(thing):
thing.quack()

# Tạo các đối tượng
duck = Duck()
person = Person()

# Sử dụng duck typing
make_it_quack(duck)    # Output: Quack, quack!
make_it_quack(person)  # Output: Tôi đang làm mời làm vịt!

Trong ví dụ này, make_it_quack không quan tâm đến kiểu của đối tượng nó nhận được. Chỉ cần đối tượng có phương thức quack, nó sẽ hoạt động.

Method Overriding trong Python

Method overriding là khi lớp con cung cấp cụ thể một cách thực hiện cho phương thức đã được định nghĩa trong lớp cơ bản của nó. Như khi bạn nói với cha mẹ của bạn, "Tôi biết bạn làm như thế này, nhưng tôi sẽ làm theo cách của mình!"

Dưới đây là một ví dụ:

class Vehicle:
def move(self):
print("Tôi đang di chuyển!")

class Car(Vehicle):
def move(self):
print("Tôi đang lái xe trên đường!")

class Boat(Vehicle):
def move(self):
print("Tôi đang chèo thuyền trên nước!")

# Tạo các đối tượng
vehicle = Vehicle()
car = Car()
boat = Boat()

# Sử dụng method overriding
vehicle.move()  # Output: Tôi đang di chuyển!
car.move()      # Output: Tôi đang lái xe trên đường!
boat.move()     # Output: Tôi đang chèo thuyền trên nước!

Trong ví dụ này, cả CarBoat đều ghi đè phương thức move của lớp Vehicle với các cách thực hiện cụ thể của chúng.

Overloading Operators trong Python

Python cho phép bạn định nghĩa cách các toán tử hành xử khi áp dụng vào các đối tượng của lớp tùy chỉnh của bạn. Điều này được gọi là operator overloading.

Dưới đây là một ví dụ:

class Point:
def __init__(self, x, y):
self.x = x
self.y = y

def __add__(self, other):
return Point(self.x + other.x, self.y + other.y)

def __str__(self):
return f"({self.x}, {self.y})"

# Tạo các đối tượng
p1 = Point(1, 2)
p2 = Point(3, 4)

# Sử dụng operator overloading
p3 = p1 + p2
print(p3)  # Output: (4, 6)

Trong ví dụ này, chúng ta đã ghi đè toán tử + cho lớp Point của chúng ta bằng cách định nghĩa phương thức __add__.

Method Overloading trong Python

Không giống như một số ngôn ngữ khác, Python không hỗ trợ method overloading trong cách truyền thống. Tuy nhiên, chúng ta có thể đạt được chức năng tương tự bằng cách sử dụng các tham số mặc định hoặc các tham số có độ dài thay đổi.

Dưới đây là một ví dụ:

class Calculator:
def add(self, *args):
return sum(args)

# Tạo một đối tượng
calc = Calculator()

# Sử dụng chức năng tương tự như method overloading
print(calc.add(1, 2))        # Output: 3
print(calc.add(1, 2, 3))     # Output: 6
print(calc.add(1, 2, 3, 4))  # Output: 10

Trong ví dụ này, phương thức add của chúng ta có thể nhận bất kỳ số lượng tham số nào, mô tả method overloading-like.

Bảng Các Phương Thức Polymorphism

Dưới đây là bảng tóm tắt các phương thức polymorphism mà chúng ta đã thảo luận:

Method Mô tả Ví dụ
Duck Typing Tập trung vào hành vi của đối tượng thay vì kiểu của nó make_it_quack(thing)
Method Overriding Lớp con cung cấp cụ thể cách thực hiện cho phương thức đã định nghĩa trong lớp cơ bản Car.move() ghi đè Vehicle.move()
Operator Overloading Định nghĩa cách các toán tử hành xử khi áp dụng vào các đối tượng của lớp tùy chỉnh Ghi đè + cho lớp Point
Method Overloading-like Sử dụng các tham số mặc định hoặc các tham số có độ dài để mô tả method overloading Calculator.add(*args)

Và thế là, các bạn đã bước ra vào thế giới thú vị của polymorphism trong Python. Hãy nhớ, luyện tập sẽ làm bạn hoàn hảo, vì vậy đừng sợ thử nghiệm các khái niệm này trong mã của bạn. Trước khi bạn biết, bạn sẽ tạo ra các chương trình thanh lịch và linh hoạt, khiến thậm chí Michelangelo cũng phải ghen tịnh!

Chúc mãi mãi mã nguồn, và may polymorphism luôn ở bên bạn!

Chúc coding vui vẻ!

Credits: Image by storyset