继承与多态
本节目标
学完这一节,你会知道:
- 什么是继承,为什么它能减少重复代码
- 子类如何获得父类的属性和方法
- 如何重写父类方法
super()用来做什么- 什么是多态
继承可以理解成:先写一个通用版本,再基于它写更具体的版本。
先跑一个例子
新建文件 inheritance_demo.py,写入:
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
print(f"{self.name} 发出了声音")
class Dog(Animal):
def speak(self):
print(f"{self.name}:汪汪!")
class Cat(Animal):
def speak(self):
print(f"{self.name}:喵喵!")
animals = [Dog("旺财"), Cat("咪咪")]
for animal in animals:
animal.speak()
运行:
python3 inheritance_demo.py
你会看到:
旺财:汪汪!
咪咪:喵喵!
Dog 和 Cat 都继承了 Animal,但各自有不同的 speak()。
什么是继承?
继承语法:
class 子类(父类):
pass
例子:
class Animal:
def eat(self):
print("正在吃东西")
class Dog(Animal):
pass
dog = Dog()
dog.eat()
Dog 没有写 eat(),但它继承了 Animal 的 eat()。
重写方法
如果子类想要自己的行为,可以重写父类方法。
class Animal:
def speak(self):
print("发出了声音")
class Dog(Animal):
def speak(self):
print("汪汪")
调用 Dog().speak() 时,会使用 Dog 自己的版本。
super()
子类经常需要先使用父类的初始化逻辑,再增加自己的属性。
class Employee:
def __init__(self, name, salary):
self.name = name
self.salary = salary
class Manager(Employee):
def __init__(self, name, salary, department):
super().__init__(name, salary)
self.department = department
super().__init__(name, salary) 表示调用父类的 __init__()。
完整例子:
manager = Manager("马哥", 30000, "技术部")
print(manager.name)
print(manager.salary)
print(manager.department)
多态
多态的意思是:不同对象可以用同一个方法名,但表现不同。
animals = [Dog("旺财"), Cat("咪咪")]
for animal in animals:
animal.speak()
循环里不需要判断它是狗还是猫,只要它有 speak() 方法就行。
这会让代码更灵活。
逐行拆解
再看开头的例子:
class Dog(Animal):
定义 Dog 类,并继承 Animal。
def speak(self):
print(f"{self.name}:汪汪!")
重写父类的 speak() 方法。
for animal in animals:
animal.speak()
同样调用 speak(),不同对象执行自己的版本。
自己改一改
把 inheritance_demo.py 改成通知系统:
class Notification:
def __init__(self, title):
self.title = title
def send(self):
print(f"发送通知:{self.title}")
class EmailNotification(Notification):
def send(self):
print(f"发送邮件:{self.title}")
class SMSNotification(Notification):
def send(self):
print(f"发送短信:{self.title}")
notifications = [
EmailNotification("新评论"),
SMSNotification("验证码"),
]
for notification in notifications:
notification.send()
然后继续改:
- 增加一个
PushNotification - 给父类增加
message属性 - 子类用
super()调用父类初始化
实战:支付方式
新建文件 payment.py:
class Payment:
def __init__(self, name):
self.name = name
def pay(self, amount):
print(f"{self.name} 支付 {amount:.2f} 元")
class WeChatPay(Payment):
def __init__(self):
super().__init__("微信")
class AliPay(Payment):
def __init__(self):
super().__init__("支付宝")
def checkout(payment, amount):
payment.pay(amount)
print("支付完成")
checkout(WeChatPay(), 99.9)
checkout(AliPay(), 199.5)
checkout() 不关心具体是哪种支付方式,只要对象有 pay() 方法。
了解即可:isinstance()
可以判断一个对象是不是某个类的实例。
dog = Dog("旺财")
print(isinstance(dog, Dog))
print(isinstance(dog, Animal))
子类对象也属于父类。
常见错误
1. 忘记调用 super()
class Manager(Employee):
def __init__(self, name, salary, department):
self.department = department
这样 name 和 salary 没有初始化。应该写:
super().__init__(name, salary)
2. 子类方法名拼错
如果父类方法叫 speak(),子类写成 speek(),就不是重写,而是新增了另一个方法。
3. 为了继承而继承
继承适合“子类是父类的一种”。比如狗是动物。
如果只是“包含关系”,比如学生有成绩,不一定要用继承。
4. 继承层级太深
继承超过两三层后,代码会变难懂。初学时尽量保持简单。
小练习
练习 1:车辆继承
定义 Vehicle 父类,再定义 Car 和 Bike 子类,重写 run() 方法。
练习 2:员工和经理
定义 Employee,包含姓名和工资。定义 Manager,增加部门属性,并使用 super()。
练习 3:统一打印
创建多个对象放进列表,循环调用同一个方法,观察多态效果。
参考答案
练习 1:
class Vehicle:
def run(self):
print("交通工具在移动")
class Car(Vehicle):
def run(self):
print("汽车在行驶")
class Bike(Vehicle):
def run(self):
print("自行车在骑行")
练习 2:
class Employee:
def __init__(self, name, salary):
self.name = name
self.salary = salary
class Manager(Employee):
def __init__(self, name, salary, department):
super().__init__(name, salary)
self.department = department
练习 3:
vehicles = [Car(), Bike()]
for vehicle in vehicles:
vehicle.run()
小结
这一节你学会了:
- 子类可以继承父类的属性和方法
- 子类可以重写父类方法
super()可以调用父类方法- 多态让不同对象用同一个接口表现出不同行为
- 继承适合表达“某某是一种某某”的关系
下一节我们会学习魔法方法。它能让你写的类支持 print()、len()、+ 等 Python 内置语法。
继承让代码少重复,多一点家族感
Animal、Dog、Cat 的例子看着简单,但它藏着很实用的复用思路。子类可以继承父类,也可以有自己的声音。马哥提醒你:继承适合“某某是一种某某”,别什么关系都硬认亲。
还没有评论,来抢沙发吧!