跳转至

继承和多态

继承

在面向对象编程中,继承是一个重要的特性,他允许我们定义一个新的类,这个类可以继承一个或者多个已有的类的属性和方法,这样就可以实现代码的复用,提高代码的可维护性.

在 Python 中,继承是通过在类定义时在类名后面加上括号指定基类来实现的.如下所示:

class Animal():
  def __init__(self,name,age) -> None:
    self.name = name
    self.age = age

  def speak(self):
    print(f"{self.name} says something")

class Dog(Animal):
  def speak(self):
    print(f"Dog: {self.name} is woof! {self.name} is {self.age} year old!")

  def run(self):
    print(f"{self.name} is running!")

class Cat(Animal):
  def speak(self):
    print(f"Cat: {self.name} is Meow! {self.name} is {self.age} year old!")


my_dog = Dog('Yuki',3)
my_dog.speak()

my_cat = Cat('Tom',1)
my_cat.speak()

在以上代码中,我们定义了Animal类,类中包含了nameage 两个属性和包含一个 speak方法,后面我们定义了DogCat 两个类,这两个类继承了 Animal类,所以Dog 和 Cat 两个类就拥有了 Animal 类 的属性和方法. 然后我们创建Dog 和 Cat 类的实例对象. 调用 speak()方法就可以输出不同的声音了,Animal 是基类(父类),Dog 和 Cat 是派生类(子类)

子类父类都存在相同的方法时,子类的方法会覆盖父类的方法.在代码运行的时候,总是会调用子类的方法.这样我们就可以根据不同子类对象调用相同方法,实现不同的功能.比如上面的 speak 方法.Dog 类和 Cat 类都有 speak 方法,但是实际调用的是子类的 speak 方法.

当我们想要在子类中调用父类的方法时,可以使用super()函数,比如下面的例子:

class Cat(Animal):
  def speak(self):
    super().speak() # 调用父类的speak方法
    print(f"Cat: {self.name} is Meow! {self.name} is {self.age} year old!")
在上面的代码中,我们在 Cat 类 speak方法调用了super().speak() 方法. 这样就可以调用父类的 speak 方法.然后再输出 Cat 类的声音

另外子类还可以继承多个父类,这种继承方式称为多重继承,比如下面的例子:

class Animal():
  def __init__(self,name,age) -> None:
    self.name = name
    self.age = age

  def speak(self):
    print(f"{self.name} says something")

class Fly():
  def fly(self):
    print(f"{self.name} is flying!")

class Cat(Animal,Fly): # 调用多个父类
  def speak(self):
    super().speak()
    print(f"Cat: {self.name} is Meow! {self.name} is {self.age} year old!")


my_cat = Cat('Tom',1)
my_cat.speak()
my_cat.fly()
上面代码中, Cat 类继承了 Animal 和Fly 两个父类,所以Cat 类就拥有了两个类的属性和方法,然后我们创建Dog 类的实例对象.调用 speak 和 fly方法就可以输出不同的声音和动作了.要继承多个父类时候,只需要在定义时在类名后面的括号中指定多个父类即可.多个父类用逗号隔开,这样就可以实现多重继承了.

多态

多态是面向对象编程的一个重要特性,他允许不同的子类对象调用不同的父类方法,但实际调用的是各自的方法.这样就可以实现不同的功能,提供代码的灵活性和扩展性.

class Animal():
  def __init__(self,name,age) -> None:
    self.name = name
    self.age = age

  def speak(self):
    print(f"{self.name} says something")

class Dog(Animal):
  def speak(self):
    print(f"Dog: {self.name} is woof! {self.name} is {self.age} year old!")

  def run(self):
    print(f"{self.name} is running!")

class Cat(Animal):
  def speak(self):
    print(f"Cat: {self.name} is Meow! {self.name} is {self.age} year old!")

def animal_speak(animal: Animal):
  animal.speak()

dog = Dog('Tom',1)
cat = Cat('lili',2)

animal_speak(dog) # 输出: Dog: Tom is woof! Tom is 1 year old!
animal_speak(cat) # 输出: Cat: lili is Meow! lili is 2 year old!

在上面的代码中,我们定义了一个 Animal 的类,这个类包含 name 和 age 属性和 speak 方法.然后我们又定义了两个类一个是Dog 类,一个是Cat 类.这两个类继承了 Animal 类,然后我们定义了一个 animal_speak() 函数,这个函数接收一个Animal 类的对象,然后调用speak方法.这样子就可以实现不同的子类对象调用相同的父类方法,但是实际调用的是各自的方法,这样就实现了多态

多态的好处? 当我们增加新的子类时,只需要继承父类并实现相应的方法即可,不需要修改父类的代码,这样就提高了代码的可扩展性和维护性.

上面我们定义了animal_speak 函数接受了一个Animal 类对象,这样就限制了传入的对象必须是Animal类的对象,由于 Dog 和 Cat 类继承了 Animal 类,这两个子类的对象实际也是Animal 类的对象,所以我们可以传入 Dog 和 Cat 类的对象.我们可以使用 isinstance 函数来判断一个对象是否是某个类的实例对象

print(isinstance(dog, Dog))
print(isinstance(cat, Cat))
print(isinstance(dog, Animal))
print(isinstance(cat, Animal))
面向对象编程的三大特性:封装、继承和多态,这三个特性是面向对象编程的基石,通过这三个特性,我们可以更好地组织代码,提高代码的可维护性和可重用性。

回到页面顶部