> 文档中心 > 【python面向对象】继承与多态(一)

【python面向对象】继承与多态(一)

文章目录

  • 继承
    • 定义
    • 优点
    • 缺点
    • 作用
    • 适用性.
  • 继承的方法
    • python内置函数
      • 1.isinstance()
      • 2.issubclass()
    • 练习
  • 继承的变量
    • 练习
  • 多态
    • 定义
    • 作用
    • 练习
  • 重写
    • 练习1
    • 练习2
  • 类与类的关系
  • 面向对象设计思想
    • 开-闭原则(目标、总的指导思想)
    • 类的单一职责(一个类的定义)
    • 依赖倒置(依赖抽象)
    • 组合复用原则(复用的最佳实践)

继承

定义

重用现有类的功能与概念,并在此基础上进行扩展。

优点

  1. 一种代码复用的方式。
  2. 以层次化的方式管理类。

缺点

耦合度高。

作用

隔离客户端代码与功能的实现方式。

适用性.

多个类在概念上是一致的,且需要进行统一的处理。

继承的方法

"""    继承--方法"""#多个子类在概念上一致的﹐所以就抽象出一个父类.#多个子类的共性﹐可以提取到父类中.#从设计角度讲∶先有子﹐再有父.#从编码角度讲∶先有父,再有子.class Person:    def say(self): print("说话")class Student(Person):    def study(self): print("学习")class Teacher(Person):    def teach(self): print("讲课")s01 = Student()#子类对象可以调用子类,也可以调用父类成员.s01.study()#学习s01.say()#说话#父类成员p01 = Person()#父类对象只可以调用父类成员,不能调用子类成员p01.say()

python内置函数

1.isinstance()

t01 = Teacher()#python 内置函数#1.判断对象是否属于一个类型#"老师对象“是一个老师类型print(isinstance(t01, Teacher))#True#"老师对象“不是一个学生类型print(isinstance(t01, Student))#False#"老师对象“是一个人类型print(isinstance(t01, Person))#True

2.issubclass()

#2.判断一个类型是否属于另一个类型#"老师类型”不是一个学生类型print(issubclass (Teacher, Student))#False#"老师类型”是一个人类型print(issubclass (Teacher , Person))# True# "人类型"不是一个老师类型print(issubclass (Person , Teacher))# False

下面的图帮助大家理解其思想:【python面向对象】继承与多态(一)

练习

定义父类:动物(行为∶叫)定义子类:狗(行为∶跑)    鸟(行为∶飞)创建三个类型的对象体会∶ isinstance(对象,类型)体会∶ issubclass(类型,类型)
class Animal:    def shout(self): print("叫")class Dog(Animal):    def run(self): print("跑")class Bird(Animal):    def fly(self): print("飞")bird = Bird()print(isinstance(bird, Bird))#Trueprint(isinstance(bird, Dog))#Falseprint(isinstance(bird, Animal))#Trueprint(issubclass(Bird,Dog))#Falseprint(issubclass(Bird,Animal))#Trueprint(issubclass(Animal,Bird))#False

继承的变量

"""    继承--变量"""class Person:    def __init__(self, name): self.name = name# 情况1"""class Student(Person):     #子类若没有构造函数,使用父类的.     passs01 = Student()print(s01.name)#AttributeError: 'Student01' object has no attribute 'name'"""class Student(Person):    #子类若具有构造函数﹐则必须先调用父类的构造函数    def __init__(self,name,score): super().__init__(name) self.score = scores01 = Student("张三",100)print(s01.score)#100print(s01.name)#张三p01 = Person("李四")print(p01.name)#李四

内存图:【python面向对象】继承与多态(一)

练习

定义父类车(数据:品牌,速度)定义子类电动车(数据︰电池容量,充电功率)创建两个对象
class Car:    """ 车    """    def __init__(self,brand,speed): self.brand = brand self.speed = speedclass Electrocar(Car):    """ 电动车    """    def __init__(self,brand,speed,battery_capacity,charging_power): super().__init__(brand,speed) self.battery_capacity = battery_capacity self.charging_power = charging_powerc01 = Car("奔驰",230)print(c01.brand)#奔驰e01 = Electrocar("比亚迪",120,15000,220)print(e01.charging_power)#220

多态

定义

父类的同一种动作或者行为,在不同的子类上有不同的实现。

作用

  1. 继承将相关概念的共性进行抽象,多态在共性的基础上,体现类型的个性化(—个行为有不同的实现)。
  2. 增强程序扩展性,体现开闭原则。
"""    多态"""#需求∶老张开车去东北#变化∶坐飞机#坐火车#骑车class Vehicle:    """ 交通工具,代表所有具体的交通工具(火车/飞机..) 继承:隔离子类变化,将子类的共性(火车/飞机..)提取到父类(运输)中。    """    def transport(self,str_position): # 因为父类太过于抽象﹐所以写不出方法体。 pass#客户端代码,用交通工具class Person:    def __init__(self,name): self.name = name    def go_to(self,vehicle,str_position): # #如果是汽车 # if type(vehicle) == Car: #     vehicle.run(str_position) # #如果是飞机 # elif type(vehicle) == Airplane: #     vehicle.fly(str_position) #多态∶调用父﹐执行子 # 调用的是交通工具的运输方法 # 执行的是飞机的运输方法或者汽车的运输方法 vehicle.transport(str_position)#-------------------以上是架构师完成的,以下是程序员完成的-------------------------------class Car(Vehicle):    # def run(self,str_position):    #     print("汽车开到" ,str_position)    def transport(self,str_position): print("汽车开到" ,str_position)class Airplane(Vehicle):    # def fly(self,str_position):    #     print("飞机飞到" ,str_position)    def transport(self,str_position): print("飞机飞到" ,str_position)p01 = Person("老张")c01 = Car()a01 = Airplane()p01.go_to(c01,"东北")#汽车开到 东北p01.go_to(a01,"东北")#飞机飞到 东北

练习

手雷炸了,可能伤害敌人/玩家的生命。还可能伤害未知事物(鸭子,房子..)要求∶增加了新事物﹐不影响手雷。体会:继承的作用多态的体现设计原则开闭原则单一职责依赖倒置

【python面向对象】继承与多态(一)

class Thing:    def harm(self,value): passclass Grenade:    def __init__(self,attack): self.attack = attack    def explode(self,thing): print("手雷炸了") thing.harm(self.attack)class  Player(Thing):    def __init__(self,hp): self.hp = hp    def harm(self,value): print("玩家原先%d血量" %self.hp) self.hp -= value print("玩家受伤了,还剩下%d血量"%self.hp)class Enemy(Thing):    def __init__(self,hp): self.hp = hp    def harm(self,value): print("敌人原先%d血量" %self.hp) self.hp -= value print("敌人受伤了,还剩下%d血量"%self.hp)p01 = Player(100)e01 = Enemy(50)g01 = Grenade(10)g01.explode(e01)# 手雷炸了# 敌人原先50血量# 敌人受伤了,还剩下40血量g01.explode(p01)# 手雷炸了# 玩家原先100血量# 玩家受伤了,还剩下90血量

重写

子类实现了父类中相同的方法(方法名、参数),在调用该方法时,实际调用的是子类的方法。

class Thing:    def harm(self,value):    #如果子类不重写﹐则异常。 raise NotImplementedError()class Grenade:    def __init__(self,attack): self.attack = attack    def explode(self,thing): # 如果变量是受伤害,则执行爆炸逻辑 if isinstance(thing,Thing):     print("手雷炸了")     thing.harm(self.attack)class  Player(Thing):    def __init__(self,hp): self.hp = hp    def harm2(self,value): print("玩家原先%d血量" %self.hp) self.hp -= value print("玩家受伤了,还剩下%d血量"%self.hp)class Enemy(Thing):    def __init__(self,hp): self.hp = hp    def harm(self,value): print("敌人原先%d血量" %self.hp) self.hp -= value print("敌人受伤了,还剩下%d血量"%self.hp)p01 = Player(100)e01 = Enemy(50)g01 = Grenade(10)g01.explode(e01)

练习1

定义图形管理器类1.管理所有图形2.提供计算所有图形总面积的方法具体图形:圆形(pi x r**2)矩形(长*宽)...测试∶创建1个圆形对象﹐1个矩形对象﹐添加到图形管理器中。调用图形管理器的计算面积方法﹐输出结果。要求∶增加新图形﹐不修改图形管理器的代码体会∶面向对象三大特征∶封装/继承/多态面向对象设计原则∶开闭/单一/倒置
#用到的思想是面向对象设计思想的前三种,见下面详细解释import mathclass   Graphics:    def area(self): # 如果子类不重写,则异常。 raise NotImplementedError()class Rotundity(Graphics):    def __init__(self,r): self.r = r    def area(self): return math.pi * self.r ** 2class Rectangle(Graphics):    def __init__(self,length,width): self.length = length self.width = width    def area(self): return self.length * self.widthclass Graphics_Manager:    def __init__(self): self.__graphics = []    def add_graphic(self, graphic): if isinstance(graphic,Graphics):     # 添加的就是图形∶     self.__graphics.append(graphic) else:     raise ValueError()    def get_total_area(self): total_area = 0 # 遍历图形列表,累加每个图形的面积 for item in self.__graphics:     # 多态∶     #调用的是图形     # 执行的是圆形/矩形...     total_area += item.area() return total_arear01 = Rectangle(10,20)r02 = Rotundity(5)g01 = Graphics_Manager()g01.add_graphic(r01)g01.add_graphic(r02)print("所有图形的面积:%.2f"%g01.get_total_area())#所有图形的面积:278.54

练习2

定义员工管理器1.管理所有员工2.计算所有员工工资员工:程序员∶底薪+项目分红销售∶底薪+销售额*0.05软件测试......要求∶增加新岗位﹐员工管理器不变
#用到的思想是面向对象设计思想的前四种,见下面详细解释class Employee_manager:    def __init__(self): self.__employee = []    def add_employee(self,employee): self.__employee.append(employee)    def get_all_wage(self): total_all_wage = 0 for item in self.__employee:     total_all_wage += item.Calculate_wage() return total_all_wageclass Employee:    def __init__(self,salary): self.salary = salary    def Calculate_wages(self): passclass Programmer(Employee):    def __init__(self,salary,project_dividends): super().__init__(salary) self.project_dividends = project_dividends    def Calculate_wage(self): return self.salary + self.project_dividendsclass Salesperson(Employee):    def __init__(self,salary,sales): super().__init__(salary) self.sales = sales    def Calculate_wage(self): return self.salary + self.sales * 0.05p01 = Programmer(20,10)s01 = Salesperson(10,100)e01 = Employee_manager()e01.add_employee(p01)e01.add_employee(s01)print("员工总工资:%.2f"%e01.get_all_wage())#员工总工资:45.00

类与类的关系

  1. 泛化:子类与父类的关系,概念的复用,耦合度最高
B类泛化A类,意味B类是A类的一种; 做法:B类继承A类
  1. 关联(聚合/组合):部分与整体的关系,功能的复用。
A与B关联,意味着B是A的一部分;做法:在A类中包含B类型成员。
  1. 依赖:合作关系,一种相对松散的协作,变化影响一个方法。
A类依赖B类,意味A类的某些功能靠B类实现;做法:B类型作为A类中方法的参数,并不是A的成员。

面向对象设计思想

开-闭原则(目标、总的指导思想)

Open Closed Principle
对扩展开放,对修改关闭。
增加新功能,不改变原有代码。

类的单一职责(一个类的定义)

Single Responsibility Principle
一个类有且只有一个改变它的原因。

依赖倒置(依赖抽象)

Dependency Inversion Principle
客户端代码(调用的类)尽量依赖(使用)抽象的组件。
抽象的是稳定的,实现是多变的。
【python面向对象】继承与多态(一)

组合复用原则(复用的最佳实践)

Composite Reuse Principle
如果仅仅为了代码复用优先选择组合复用,而非继承复用。
组合的耦合性相对继承低。
【python面向对象】继承与多态(一)