6.1 继承 — 简单搞定
继承是面向对象编程 (OOP) 的一个基本概念,它允许一个类(称为子类或派生类)继承另一个类(称为父类或超类)的字段和方法。
这种方法可以创建更通用的类和重用代码,从而提高代码的组织性和可维护性。
为啥要用继承?
假设你需要写一些代码,你决定用类来实现。然后你发现你的项目中已经有一个类,几乎能完成你需要的工作。你可以简单地复制这个类的代码到自己的类中,然后开开心心地用。
或者你可以「像复制一样」。你可以将那个类声明为你类的父类,这样 Python 就会给你的类加上父类的行为。
想象一下,你是大自然,想要创造一只狗。是用十亿年从细菌开始进化一只狗更快,还是用二十万年驯化一只狼更快?
基本继承的例子
假设你有一个父类 Animal,它有一个字段 name:
class Animal:
def __init__(self, name):
self.name = name
我们想为它创建两个子类 — Dog 和 Cat,并为它们都添加一个 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!"
在上面的例子中,子类 Dog 和 Cat 从 Animal 中继承,并添加了 speak 方法。
类 Dog:
- 从
Animal继承属性name。 - 添加了一个返回狗特定字符串的
speak方法。
类 Cat:
- 从
Animal继承属性name。 - 添加了一个返回猫特定字符串的
speak方法。
最终的代码看起来是这样的:
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()) # 输出:Buddy says Woof!
print(cat.speak()) # 输出:Whiskers says Meow!
在这个例子中,Animal 是父类,Dog 和 Cat 是子类。子类继承了父类 Animal 的属性 name 和方法 __init__,但是增加了 speak 方法。
6.2 继承的内部机制
如果你给你的类加了个父类,这很像是你复制了父类的代码到你的类中。
class Animal:
def __init__(self, name):
self.name = name
class Dog(Animal):
def __init__(self, name):
super().__init__(name) # 调用父类构造函数
def speak(self):
return f"{self.name} says Woof!"
class Cat(Animal):
def __init__(self, name):
super().__init__(name) # 调用父类构造函数
def speak(self):
return f"{self.name} says Meow!"
dog = Dog("Buddy")
cat = Cat("Whiskers")
print(dog.speak()) # 输出:Buddy says Woof!
print(cat.speak()) # 输出:Whiskers says Meow!
这不是一个完全准确的描述,但如果你从未接触过继承的概念,你可以暂时这样理解。我们稍后会添加更多细节。
6.3 继承的层次结构
设计复杂模型的大型类群时,你常常会遇到完整的继承层次结构。
例如,你有一个 Animal 类——这是所有动物的基类:
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
raise NotImplementedError("Subclass must implement abstract method")
我们甚至给它加了一个 speak 方法,但由于抽象的动物不说话,这个方法只是抛出一个 NotImplementedError 异常——这是标准做法。
然后我们添加中间类,代表动物的类别:Mammal 是哺乳动物,Bird 是鸟类。
class Mammal(Animal):
def __init__(self, name, fur_color):
super().__init__(name) # 调用父类构造函数
self.fur_color = fur_color
class Bird(Animal):
def __init__(self, name, wing_span):
super().__init__(name) # 调用父类构造函数
self.wing_span = wing_span
def fly(self):
return f"{self.name} is flying with a wingspan of {self.wing_span} meters."
最后,只有在最终阶段才出现特定动物种类的类:
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!"
最终的代码如下:
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.") # 输出:Buddy has brown fur.
print(f"{cat.name} has {cat.fur_color} fur.") # 输出:Whiskers has white fur.
print(parrot.fly()) # 输出:Polly is flying with a wingspan of 0.5 meters.
虽然技术上没有禁止创建有数十个祖先的继承层次结构,但重要的是要记住,在没有必要的情况下,最好保持简单。简单就是力量。
GO TO FULL VERSION