Skip to content

11.1 继承语法与子类创建

继承是面向对象编程的三大特性之一,它允许我们基于已有的类创建新类。新类会自动获得父类的所有属性和方法,这就是"站在巨人的肩膀上"写代码!

在Python中,创建子类的语法非常简单:在定义类时,在括号中指定父类名称即可。

python
# 定义父类
class Animal:
    def __init__(self, name):
        self.name = name  # 父类的实例属性
    
    def speak(self):
        print(f"{self.name} 发出声音")  # 父类的方法

# 定义子类,继承自Animal
class Dog(Animal):  # Dog类继承了Animal类
    def __init__(self, name, breed):
        super().__init__(name)  # 调用父类的构造方法
        self.breed = breed  # 子类特有的属性

# 创建子类实例
my_dog = Dog("旺财", "金毛")
print(my_dog.name)   # 可以访问父类的属性
print(my_dog.breed)  # 可以访问子类的属性
my_dog.speak()       # 可以调用父类的方法

继承的好处显而易见:避免重复代码,提高代码复用性。子类可以拥有父类的所有功能,同时还能添加自己的特色功能。

11.2 方法重写基础

有时候父类的方法不能完全满足子类的需求,这时候就需要方法重写(也叫方法覆盖)。子类可以定义与父类同名的方法,这样在调用时就会优先使用子类的方法。

python
# 父类
class Animal:
    def __init__(self, name):
        self.name = name
    
    def speak(self):
        print(f"{self.name} 发出声音")

# 子类重写父类的speak方法
class Cat(Animal):
    def __init__(self, name, color):
        super().__init__(name)
        self.color = color
    
    # 重写父类的speak方法
    def speak(self):
        print(f"{self.name} 喵喵叫")  # 子类特有的实现

# 子类也可以选择不重写
class Bird(Animal):
    pass  # Bird类直接使用父类的speak方法

# 测试方法重写
my_cat = Cat("咪咪", "白色")
my_bird = Bird("小黄")

my_cat.speak()   # 输出: 咪咪 喵喵叫 (调用子类重写的方法)
my_bird.speak()  # 输出: 小黄 发出声音 (调用父类的方法)

方法重写让我们能够为不同的子类提供特定的行为实现,这是实现多态的基础。

11.3 super() 函数简单使用

super() 函数是处理继承关系的利器,它返回一个代理对象,让你能够调用父类的方法。最常见的用途是在子类的 __init__ 方法中调用父类的构造方法。

python
# 父类
class Vehicle:
    def __init__(self, brand, model):
        self.brand = brand
        self.model = model
        self.is_running = False
    
    def start(self):
        self.is_running = True
        print(f"{self.brand} {self.model} 启动了")
    
    def stop(self):
        self.is_running = False
        print(f"{self.brand} {self.model} 停止了")

# 子类使用super()调用父类方法
class Car(Vehicle):
    def __init__(self, brand, model, doors):
        super().__init__(brand, model)  # 调用父类构造方法
        self.doors = doors
    
    def start(self):
        super().start()  # 先调用父类的start方法
        print("汽车启动,准备出发!")  # 再执行子类特有的逻辑
    
    def honk(self):  # 子类特有的方法
        if self.is_running:
            print("滴滴!")
        else:
            print("汽车未启动,无法按喇叭")

# 使用示例
my_car = Car("丰田", "卡罗拉", 4)
my_car.start()  # 会先调用父类start,再执行子类的额外逻辑
my_car.honk()
my_car.stop()

使用 super() 的好处是代码更加灵活,如果父类名称发生变化,子类代码不需要修改。

提示

需要留意的是,在多重继承(一个子类同时继承多个父类)时,super() 会按照 MRO(方法解析顺序)去查找下一个方法,并不一定是直接父类。初学者掌握单继承中的用法即可,深入学习继承体系时可再研究 MRO。

11.4 多态的简单理解

多态是指同一个接口可以有不同的实现方式。在Python中,由于是动态类型语言,多态体现得更加自然——我们不需要关心对象的具体类型,只要它有相应的方法就可以。

python
# 定义多个具有相同接口的类
class Dog:
    def speak(self):
        return "汪汪汪"

class Cat:
    def speak(self):
        return "喵喵喵"

class Duck:
    def speak(self):
        return "嘎嘎嘎"

# 多态函数:接受任何有speak方法的对象
def animal_sound(animal):
    # 不关心animal具体是什么类型,只要有speak方法就行
    print(animal.speak())

# 创建不同类型的对象
animals = [Dog(), Cat(), Duck()]

# 对所有动物调用相同的方法,但得到不同的结果
for animal in animals:
    animal_sound(animal)  # 多态的体现

# 另一个多态示例:计算不同形状的面积
class Rectangle:
    def __init__(self, width, height):
        self.width = width
        self.height = height
    
    def area(self):
        return self.width * self.height

class Circle:
    def __init__(self, radius):
        self.radius = radius
    
    def area(self):
        return 3.14159 * self.radius ** 2

# 多态函数计算面积
def calculate_area(shape):
    return shape.area()  # 不关心shape是矩形还是圆形

# 使用多态
shapes = [Rectangle(5, 3), Circle(4)]
for shape in shapes:
    print(f"面积: {calculate_area(shape)}")

多态让我们的代码更加通用和灵活,这也是面向对象编程的魅力所在。通过多态,我们可以编写出能够处理多种不同类型对象的通用函数。