前置知识
封装
- 详解文章:https://www.cnblogs.com/poloyy/p/15203989.html
- 封装根据职责将属性、方法封装到一个抽象的类中
- 定义类的准则-封装
继承
- 详解文章:https://www.cnblogs.com/poloyy/p/15216652.html
- 继承实现代码的重用,相同的代码不需要重复的编写
多态
- 不同的子类对象调用相同的父类方法,产生不同的执行结果
- 以继承和重写父类方法为前提
- 是调用方法的技巧,不会影响到类的内部设计
程序猿和设计师都是人类,他们都重写了父类的 work 方法,但他们都有自己的实现逻辑
多态的栗子一
需求
- 定义 Dog 类封装方法 game,普通狗狗简单玩耍
- 定义 ChaiQuan 继承 Dog,重写 game 方法,柴犬疯疯癫癫的玩耍
- 定义 Person 类,封装一个和狗玩的方法,在方法内部,直接调用狗对象调用玩耍的方法
类图
实际代码
class Dog:def __init__(self, name):self.name = namedef game(self):print(f\"{self.name} 狗狗在玩耍\")class ChaiQuan(Dog):def game(self):print(f\"{self.name} 柴犬在疯疯癫癫的玩耍\")class Person:def __init__(self, name):self.name = namedef gameWithDog(self, dog):print(f\"{self.name} 正在和 {dog.name} 愉快的玩耍\")# 直接通过狗实例对象调用 game 实例方法,不需要关心是哪种狗dog.game()chai = ChaiQuan(\"小柴犬\")dog = Dog(\"旺财\")p = Person(\"小菠萝\")p.gameWithDog(chai)p.gameWithDog(dog)# 输出结果小菠萝 正在和 小柴犬 愉快的玩耍小柴犬 柴犬在疯疯癫癫的玩耍小菠萝 正在和 旺财 愉快的玩耍旺财 狗狗在玩耍
- Person 类中只需要让狗对象调用 game 方法,而不用关心具体是什么狗
- game 方法是在 Dog 父类中定义的
- 在程序执行时,传入不同的狗对象参数,gameWithDog 就会产生不同的执行结果
通过统一函数接口实现多态
class Dog(object):def sound(self):print(\"汪汪汪.....\")class Cat(object):def sound(self):print(\"喵喵喵.....\")def make_sound(animal):# 统一调用接口# 不管你传进来是什么动物,我都调用sound()方法animal.sound()dogObj = Dog()catObj = Cat()make_sound(dogObj)make_sound(catObj)# 输出结果汪汪汪.....喵喵喵.....
通过抽象类实现多态
需求
- 定义一个 Person 类,可以开车,也可以停车
- 定义一个 Car 类,提供 drive、stop 的方法
- 定义一个 Truck、BaoMa 类,继承 Car 类,重写 drive、stop 方法
类图
实际代码
class Car:def __init__(self, name):self.name = namedef drive(self):# 抛出异常是防止通过 Car 直接定义实例对象# 如果 Car 的实例对象调用此方法会报错,必须由子类重写才正确raise NotImplementedError(\"Subclass must implement abstract method\")def stop(self):raise NotImplementedError(\"Subclass must implement abstract method\")class Truck(Car):def drive(self):print(f\"{self.name} Truck 准备上路了\")def stop(self):print(f\"{self.name} Truck 准备停车\")class BaoMa(Car):def drive(self):print(f\"{self.name} BaoMa 要跑到100km/h了\")def stop(self):print(f\"{self.name} BaoMa 漂移停车\")class Person:def __init__(self, name):self.name = namedef driveCar(self, car):print(f\"{self.name} 准备开车上路了\")car.drive()def stopCar(self, car):print(f\"{self.name} 准备靠边停车\")car.stop()person = Person(\"小菠萝\")truck = Truck(\"小卡车\")baoma = BaoMa(\"大宝马\")person.driveCar(truck)person.stopCar(baoma)# 输出结果小菠萝 准备开车上路了小卡车 Truck 准备上路了小菠萝 准备靠边停车大宝马 BaoMa 漂移停车
Car 是一个抽象类,并不需要通过它创建实例对象,所以 Car 的实例方法都会抛出异常,由子类继承 Car,然后重写方法才能正常调用