Kế thừa

Python SELF VI
Mức độ , Bài học
Có sẵn

6.1 Kế thừa — đơn giản mà

Kế thừa là một khái niệm cơ bản trong lập trình hướng đối tượng (OOP), cho phép một lớp (gọi là lớp con hoặc subclass) kế thừa các thuộc tính và phương thức của một lớp khác (gọi là lớp cha hoặc superclass).

Cách tiếp cận này giúp tạo ra các lớp tổng quát hơn và tái sử dụng mã, cải thiện tổ chức và khả năng bảo trì mã.

Tại sao cần kế thừa?

Giả sử bạn cần viết một đoạn mã, và bạn quyết định làm điều đó dưới dạng một lớp. Sau đó, bạn phát hiện rằng trong dự án của bạn đã có một lớp làm gần như tất cả những gì bạn cần trong lớp của mình. Bạn có thể đơn giản sao chép mã của lớp đó vào lớp của mình và thoải mái sử dụng.

Hoặc bạn có thể "giống như sao chép". Bạn có thể tuyên bố lớp đó là cha của lớp mình, và sau đó Python sẽ thêm vào lớp của bạn hành vi của lớp cha.

Tưởng tượng bạn là thiên nhiên và muốn tạo ra một con Chó. Điều nào sẽ nhanh hơn—tạo chó từ vi khuẩn trong một tỷ năm hay thuần hóa sói trong 200 nghìn năm?

Ví dụ về kế thừa cơ bản

Giả sử bạn có một lớp cha là Animal với thuộc tính name:


class Animal:
    def __init__(self, name):
        self.name = name

Chúng ta muốn tạo 2 lớp con cho nó — DogCat, và thêm cho chúng phương thức speak:


class Dog(Animal):
    def speak(self):
        return f"{self.name} says Woof!"

class Cat(Animal):
    def speak(self):
        return f"{self.name} says Meow!"

Trong ví dụ trên, các lớp con DogCat kế thừa từ Animal và thêm phương thức speak.

Đối tượng lớp Dog:

  • Kế thừa thuộc tính name từ Animal.
  • Thêm phương thức speak, trả về chuỗi đặc trưng cho chó.

Đối tượng lớp Cat:

  • Kế thừa thuộc tính name từ Animal.
  • Thêm phương thức speak, trả về chuỗi đặc trưng cho mèo.

Phiên bản cuối cùng của mã trông như thế này:


class Animal:
    def __init__(self, name):
        self.name = name
         
class Dog(Animal):
    def speak(self):
        return f"{self.name} says Woof!"
        
class Cat(Animal):
    def speak(self):
        return f"{self.name} says Meow!"
         
dog = Dog("Buddy")
cat = Cat("Whiskers")
        
print(dog.speak())  # Xuất: Buddy says Woof!
print(cat.speak())  # Xuất: Whiskers says Meow!

Trong ví dụ này, Animal là lớp cha, còn DogCat là các lớp con. Các lớp con kế thừa thuộc tính name và phương thức __init__ từ lớp cha Animal, nhưng thêm các phương thức speak.

6.2 Bên dưới nắp ca-pô của kế thừa

Nếu bạn đã thêm cha cho lớp của mình, điều này rất giống như bạn đã sao chép mã của lớp cha vào lớp của mình.


class Animal:
    def __init__(self, name):
        self.name = name
         

class Dog(Animal):
    def __init__(self, name):
        super().__init__(name)  # Gọi constructor của lớp cha
        
    def speak(self):
        return f"{self.name} says Woof!"
        
class Cat(Animal):
    def __init__(self, name):
        super().__init__(name)  # Gọi constructor của lớp cha
        
    def speak(self):
        return f"{self.name} says Meow!"
        

dog = Dog("Buddy")
cat = Cat("Whiskers")
        
print(dog.speak())  # Xuất: Buddy says Woof!
print(cat.speak())  # Xuất: Whiskers says Meow!

Đây không phải là mô tả chính xác, nhưng nếu bạn chưa từng đối mặt với khái niệm kế thừa, bạn có thể nghĩ về nó như vậy tạm thời. Sau này chúng ta sẽ thêm chi tiết vào đây.

6.3 Hệ thống phân cấp kế thừa

Rất thường xuyên, khi thiết kế mô hình phức tạp của một nhóm lớp lớn, bạn có thể gặp phải một hệ thống phân cấp kế thừa toàn bộ.

Ví dụ, bạn có một lớp Animal — đó là lớp cơ bản cho tất cả động vật:


class Animal:
    def __init__(self, name):
        self.name = name
        
    def speak(self):
        raise NotImplementedError("Subclass must implement abstract method")

Chúng ta thậm chí đã thêm cho nó phương thức speak, nhưng vì động vật trừu tượng không nói, phương thức này chỉ ném ra ngoại lệ NotImplementedError — đây là một thực tiễn tiêu chuẩn.

Sau đó, chúng ta thêm các lớp trung gian, tương ứng với các loại động vật: Mammal — là động vật có vú và Bird cho loài chim.


class Mammal(Animal):
    def __init__(self, name, fur_color):
        super().__init__(name)  # Gọi constructor của lớp cha
        self.fur_color = fur_color
         

class Bird(Animal):
    def __init__(self, name, wing_span):
        super().__init__(name)  # Gọi constructor của lớp cha
        self.wing_span = wing_span
        
    def fly(self):
        return f"{self.name} is flying with a wingspan of {self.wing_span} meters."

Và cuối cùng, chỉ ở giai đoạn cuối mới xuất hiện các lớp của loài động vật cụ thể:


class Dog(Mammal):
    def speak(self):
        return f"{self.name} says Woof!"
         
        
class Cat(Mammal):
    def speak(self):
        return f"{self.name} says Meow!"
        
class Parrot(Bird):
    def speak(self):
        return f"{self.name} says Squawk!"

Đây là cách mà mã cuối cùng hoạt động:


animals = [Dog("Buddy", "brown"), Cat("Whiskers", "white"), Parrot("Polly", 0.5)]
            
for animal in animals:
    print(animal.speak())

print(f"{dog.name} has {dog.fur_color} fur.")  # Xuất: Buddy has brown fur.
print(f"{cat.name} has {cat.fur_color} fur.")  # Xuất: Whiskers has white fur.
print(parrot.fly())  # Xuất: Polly is flying with a wingspan of 0.5 meters.

Mặc dù về mặt kỹ thuật không có cấm tạo hệ thống phân cấp với hàng chục lớp cha, nhưng cần nhớ rằng nếu không cần thiết, tốt nhất là nên giữ mọi thứ đơn giản. Sự đơn giản là sức mạnh.

1
Опрос
Lớp và OOP,  15 уровень,  6 лекция
недоступен
Lớp và OOP
Lớp và OOP
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION