面向对象的三大特性:封装、继承、多态
- 封装:将数据和方法封装在一个类中
- 继承:python中一个类可以继承一个或多个类,被继承的类叫父类/基类,继承的类叫子类
- 多态:指的是一个类是有多种形态,一个抽象类有多个子类,所以多态的概念依赖于继承。表现于:不同的子类对象调用相同的方法时,会产生不同的执行结果。多态可以增加代码的灵活性
比如说:继承Animal类的有cat类和dog类
注意:Python中函数的参数是没有类型限制的,所以多态在python中的体现并不是很严谨。多态的概念是应用于java和c#这类强类型语言中,而python只有“鸭子类型”(所以,python没有多态)
鸭子类型的体现:(面试)
1.静态语言:对于静态语言(比如java),上面例子中,传入对象的类型必须是Animal类或者它的子类。否则会报错,并无法执行run()方法
2.动态语言:对于动态语言(比如python),上面例子中,传入对象的类型不需要是Animal类或者它的子类。只要传入的这个类或它的父类实现了run()方法,都能够调用run()方法【鸭子类型的体现】多态的意义:开放封闭原则(面试)
1.对于一个变量,我们只需要知道它是Base类型,无需确切知道它的子类型,就可以放心地调用共有的方法(比如上面的run())。调用方只管调用,不需要管实现细节。
2.当需要新增功能时,只需要新增一个Base类的子类去实现这个新增的功能,就可以在原来的基础上进行功能的扩展,这就是“开放封闭”原则
a.对扩展开放:允许新增Base子类,以及重写Base类的方法
b.对修改封闭:不需要修改Base类已实现的函数下面代码是“伪多态”,述说下多态的例子以及多态的作用
class Animal(object):
def run(self):
print('动物都会跑')
# 都是继承Animal类,但是有不同的形态
class Cat(Animal):
def run(self):
print('猫还会爬树')
class Dog(Animal):
def run(self):
print('狗不会爬树')
print(isinstance(Cat(), Animal)) # True
print(isinstance(Dog(), Animal)) # True
"""多态的作用"""
# 定义一个函数,用于接收Animal类型的对象,包括其子类
def func(obj): # 这里在强类型语言中,需要限制传入参数的类型。比如说 public static void func(Animal animal){...}
obj.run()
# 这个时候,分别传入Cat类和Dog类,会根据不同的对象执行不同的事情
# 这就是多态的体现
func(Cat()) # 猫还会爬树
func(Dog()) # 狗不会爬树
# 接着再定义一个类,也继承Animal方法,但是没有run方法
class Bird(Animal):
pass
# 这时候把这个类传入到刚才的func()类中
# 依旧能运行,调用了父类Animal类的run()方法
func(Bird()) # 动物都会跑