面向对象继承
什么是继承
继承是面向对象编程的核心概念之一,它允许一个类(子类)基于另一个类(父类)来创建,继承父类的属性和方法。
# 父类
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
pass
# 子类
class Dog(Animal):
def speak(self):
return f"{self.name}: 汪汪!"
class Cat(Animal):
def speak(self):
return f"{self.name}: 喵喵!"
# 使用继承
dog = Dog("旺财")
cat = Cat("咪咪")
print(dog.speak()) # 输出: 旺财: 汪汪!
print(cat.speak()) # 输出: 咪咪: 喵喵!
方法重写
子类可以重写父类的方法,实现特定的行为。
class Vehicle:
def __init__(self, brand, model):
self.brand = brand
self.model = model
def describe(self):
return f"{self.brand} {self.model}"
class Car(Vehicle):
def __init__(self, brand, model, doors):
super().__init__(brand, model)
self.doors = doors
def describe(self):
return f"{super().describe()},{self.doors}门轿车"
class Truck(Vehicle):
def __init__(self, brand, model, payload):
super().__init__(brand, model)
self.payload = payload
def describe(self):
return f"{super().describe()},载重{self.payload}吨"
# 使用示例
car = Car("丰田", "卡罗拉", 4)
truck = Truck("沃尔沃", "FH16", 40)
print(car.describe()) # 输出: 丰田 卡罗拉,4门轿车
print(truck.describe()) # 输出: 沃尔沃 FH16,载重40吨
super()函数
super()函数用于调用父类的方法,避免直接引用父类名称。
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def introduce(self):
return f"我叫{self.name},今年{self.age}岁"
class Employee(Person):
def __init__(self, name, age, employee_id, salary):
super().__init__(name, age)
self.employee_id = employee_id
self.salary = salary
def introduce(self):
return f"{super().introduce()},工号{self.employee_id}"
# 使用示例
emp = Employee("张三", 25, "E001", 50000)
print(emp.introduce()) # 输出: 我叫张三,今年25岁,工号E001
多态
多态允许不同类的对象对同一方法做出不同的响应。
class Shape:
def area(self):
pass
def describe(self):
return f"这是一个形状,面积是{self.area()}"
class Circle(Shape):
def __init__(self, radius):
self.radius = radius
def area(self):
return 3.14159 * self.radius ** 2
class Rectangle(Shape):
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width * self.height
class Triangle(Shape):
def __init__(self, base, height):
self.base = base
self.height = height
def area(self):
return 0.5 * self.base * self.height
# 多态示例
shapes = [Circle(5), Rectangle(4, 6), Triangle(3, 8)]
for shape in shapes:
print(shape.describe())
# 输出:
# 这是一个形状,面积是78.53975
# 这是一个形状,面积是24
# 这是一个形状,面积是12.0
MRO(方法解析顺序)
Python使用C3线性化算法确定方法解析顺序,解决多重继承中的方法调用问题。
class A:
def method(self):
print("A.method")
class B(A):
def method(self):
print("B.method")
super().method()
class C(A):
def method(self):
print("C.method")
super().method()
class D(B, C):
pass
# 查看MRO
print(D.__mro__)
# 输出: (<class 'D'>, <class 'B'>, <class 'C'>, <class 'A'>, <class 'object'>)
# 方法调用顺序
d = D()
d.method()
# 输出:
# B.method
# C.method
# A.method
抽象类
抽象类不能被实例化,用于定义接口规范。
from abc import ABC, abstractmethod
class Database(ABC):
@abstractmethod
def connect(self):
pass
@abstractmethod
def query(self, sql):
pass
@abstractmethod
def close(self):
pass
class MySQL(Database):
def connect(self):
print("连接到MySQL数据库")
def query(self, sql):
print(f"执行SQL: {sql}")
def close(self):
print("关闭MySQL连接")
# db = Database() # 错误!不能实例化抽象类
db = MySQL()
db.connect()
db.query("SELECT * FROM users")
db.close()
最佳实践
- 使用继承表达"is-a"关系,避免滥用继承
- 优先使用组合而非继承来实现代码复用
- 使用
super()调用父类方法,避免直接引用父类名称 - 在多重继承中注意MRO顺序,避免方法冲突
- 使用抽象类定义接口规范,确保子类实现必要方法
- 保持继承层次简单,避免过深的继承链
继承是面向对象编程的强大特性,合理使用能大大提高代码的复用性和可维护性。