本章学习链接如下:
Python 面向对象——1.基本概念
Python 面向对象——2.类与对象实例属性补充解释,self的作用等
Python 面向对象——3.实例方法,类方法与静态方法
Python 面向对象——4.继承
1.基本概念
多态是面向对象编程(OOP)的一个核心概念,指的是不同类的对象可以通过同一接口(即相同的方法或属性)执行不同的操作。
Python 的内置函数 len()
是多态性的一个非常好的例子。len()
函数能够接受不同类型的参数,比如列表、字符串、元组、字典等,并返回这些数据结构的长度。尽管这些数据类型在内部结构上可能完全不同,len()
仍然可以处理它们,因为它们共享一个公共接口,即它们都是可迭代的,并且实现了返回集合大小的内部方法。
比如如下代码:
len()
函数分别用于字符串、列表和字典。尽管这些类型在内部数据的存储和处理方式上有所不同,len()
函数都能够返回正确的长度,这表明 len()
函数展示了多态行为。
# 对字符串使用 len()
print(len("Hello")) # 输出: 5
# 对列表使用 len()
print(len([1, 2, 3, 4])) # 输出: 4
# 对字典使用 len()
print(len({1: 'one', 2: 'two', 3: 'three'})) # 输出: 3
len()
实际上调用了对象的 __len__()
方法。因此,任何想要支持 len()
函数的自定义类都应该实现一个 __len__()
方法。 在下面这个代码中,BookCollection
类定义了 __len__()
方法,该方法返回集合中书籍的数量。当 len()
被调用时,它实际上调用的是 my_books.__len__()
,这符合多态的概念,因为 len()
可以与任何定义了 __len__()
方法的对象一起工作,而不需要关心对象的具体类型。
class BookCollection:
def __init__(self, books):
self.books = books
def __len__(self):
return len(self.books)
# 创建一个BookCollection实例
my_books = BookCollection(["Book1", "Book2", "Book3"])
# 使用len()
print(len(my_books)) # 输出: 3
2.代码示例
下面是一个使用Python实现多态的示例,其中定义了两个类:Dog
和Cat
,它们都继承自一个名为Animal
的基类。这些类都实现了一个make_sound()
方法,该方法在每个类中表现不同。
在这个示例中:
- 在
Animal
类中定义了一个名为make_sound
的方法。这个方法是实例方法,因为它的第一个参数是self
,它代表类的实例。make_sound
方法中没有提供任何实现,而是抛出了一个NotImplementedError
异常。这意味着Animal
类中的make_sound
方法是一个抽象方法,它要求任何继承自Animal
的子类都必须实现这个方法。这是多态性的一种实现方式,允许不同的子类以不同的方式实现相同的接口。 Dog
和Cat
类继承了Animal
类,并实现了各自版本的make_sound()
方法。Dog
类重写了make_sound
方法,并提供了一个实现,当调用时返回字符串"Woof!"
。Cat
的类,它也继承自Animal
类。Cat
类同样重写了make_sound
方法,并提供了一个实现,当调用时返回字符串"Meow!"
。animal_sound()
函数接受任何Animal
的实例作为参数,并调用其make_sound()
方法。函数内部调用传入对象的make_sound
方法,并将结果打印出来。这里利用了多态性,因为animal
参数可以是任何继承自Animal
类的实例,而函数并不关心传入的是哪种具体的动物。
class Animal:
def make_sound(self):
raise NotImplementedError("Subclasses must implement this method")
class Dog(Animal):
def make_sound(self):
return "Woof!"
class Cat(Animal):
def make_sound(self):
return "Meow!"
def animal_sound(animal):#定义了一个名为animal_sound的函数,它接受一个参数animal。
print(animal.make_sound())
# 创建Dog和Cat的实例
dog = Dog()
cat = Cat()
# 通过相同的接口调用不同的实现
animal_sound(dog)
animal_sound(cat)