Skip to content

27|继承与多态

多个类有相同的属性和方法时,可以把公共部分提取到一个父类,子类继承父类后自动拥有这些公共部分。子类还可以添加自己的特性,或修改父类的行为。

一、继承

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

    def speak(self):
        raise NotImplementedError("子类必须实现这个方法")


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("Kitty")
print(dog.speak())   # Buddy says woof
print(cat.speak())   # Kitty says meow

Dog(Animal) 表示 Dog 继承自 AnimalDog 自动拥有 Animal__init__ 方法,但重写了 speak 方法。

二、调用父类方法

子类需要在父类的基础上扩展时,用 super() 调用父类方法:

python
class Student:
    def __init__(self, name, age):
        self.name = name
        self.age = age


class GraduateStudent(Student):
    def __init__(self, name, age, major):
        super().__init__(name, age)   # 调用父类的 __init__
        self.major = major

grad = GraduateStudent("Alice", 24, "CS")
print(grad.name)    # Alice
print(grad.major)   # CS

super() 返回父类的代理对象,通过它调用父类的方法。在多重继承时,super() 按 MRO(方法解析顺序)查找下一个类,不一定是直接父类。

三、方法重写

子类重写父类的方法:

python
class Rectangle:
    def __init__(self, width, height):
        self.width = width
        self.height = height

    def area(self):
        return self.width * self.height

    def describe(self):
        return f"矩形,面积={self.area()}"


class Square(Rectangle):
    def __init__(self, side):
        super().__init__(side, side)

    def describe(self):
        return f"正方形,面积={self.area()}"


sq = Square(5)
print(sq.describe())   # 正方形,面积=25

Square 继承 Rectangle,重写了 __init__(强制宽和高相等)和 describe(修改描述文本)。

四、多态

不同的子类对象可以响应同一个方法调用,各自执行自己的实现:

python
animals = [Dog("Buddy"), Cat("Kitty")]

for animal in animals:
    print(animal.speak())
# Buddy says woof
# Kitty says meow

animal.speak() 的具体行为取决于 animal 实际是什么类的对象。Python 是动态类型语言,多态不需要显式声明接口——只要对象有 speak 方法,就能调用。

五、类型检查

判断对象是否是某个类的实例:

python
dog = Dog("Buddy")
isinstance(dog, Dog)      # True
isinstance(dog, Animal)   # True,Dog 是 Animal 的子类
isinstance(dog, Cat)      # False

判断类之间的继承关系:

python
issubclass(Dog, Animal)   # True
issubclass(Cat, Dog)      # False

六、抽象基类

如果父类的方法不应该被直接调用(如 Animal.speak),可以把父类定义为抽象基类:

python
from abc import ABC, abstractmethod

class Animal(ABC):
    @abstractmethod
    def speak(self):
        pass

# 不能直接实例化抽象类
animal = Animal()   # TypeError: Can't instantiate abstract class

子类必须实现所有抽象方法才能实例化:

python
class Dog(Animal):
    def speak(self):
        return "woof"

dog = Dog()   # 可以,实现了 speak

抽象基类强制子类实现特定方法,适合定义接口规范的场景。

七、多重继承

Python 支持一个类继承多个父类:

python
class Flyable:
    def fly(self):
        return "flying"

class Swimmable:
    def swim(self):
        return "swimming"

class Duck(Animal, Flyable, Swimmable):
    def speak(self):
        return "quack"

duck = Duck("Donald")
print(duck.speak())   # quack
print(duck.fly())     # flying
print(duck.swim())    # swimming

多重继承的复杂性在于方法解析顺序(MRO)。如果多个父类有同名方法,Python 按 MRO 顺序查找。可以通过 ClassName.__mro__ 查看解析顺序。

多重继承能简化代码,但也增加了理解成本。类层次简单时,组合(把一个类的实例作为另一个类的属性)通常比多重继承更清晰。

记忆锚点class Child(Parent) 继承;super() 调用父类方法;子类重写父类方法实现多态;isinstance() 判断对象类型,issubclass() 判断继承关系;@abstractmethod 定义抽象方法,强制子类实现;多重继承按 MRO 顺序解析;优先用组合替代复杂的多重继承。