面向对象文档

  1. 面向对象 Object Oriented

  2. 概述

  3. 面向过程

  1. 分析出解决问题的步骤,然后逐步实现。

例如:婚礼筹办

-- 发请柬(选照片、措词、制作)

-- 宴席(场地、找厨师、准备桌椅餐具、计划菜品、购买食材)

-- 婚礼仪式(定婚礼仪式流程、请主持人)

  1. 公式:程序 = 算法 + 数据结构

  2. 优点:所有环节、细节自己掌控。

  3. 缺点:考虑所有细节,工作量大。

  1. 面向对象

  1. 找出解决问题的人,然后分配职责。

例如:婚礼筹办

-- 发请柬:找摄影公司(拍照片、制作请柬)

-- 宴席:找酒店(告诉对方标准、数量、挑选菜品)

-- 婚礼仪式:找婚庆公司(对方提供司仪、制定流程、提供设备、帮助执行)

  1. 公式:程序 = 对象 + 交互

  2. 优点

  1. 思想层面:

-- 可模拟现实情景,更接近于人类思维。

-- 有利于梳理归纳、分析解决问题。

  1. 技术层面:

-- 高复用:对重复的代码进行封装,提高开发效率。

-- 高扩展:增加新的功能,不修改以前的代码。

-- 高维护:代码可读性好,逻辑清晰,结构规整。

  1. 缺点:学习曲线陡峭。

  1. 类和对象

  1. 类:一个抽象的概念,即生活中的”类别”。

  2. 对象:类的具体实例,即归属于某个类别的”个体”。

  3. 类是创建对象的”模板”。

-- 数据成员名词类型状态

-- 方法成员动词类型行为

  1. 类与类行为不同,对象与对象数据不同。

  1. 语法

Self 指向的是对象地址, .是包含的

  1. 定义类

  1. 代码

class 类名:

“””文档说明”””

def _init_(self,参数列表):

self.实例变量 = 参数

方法成员


  1. 说明

-- 类名所有单词首字母大写.

-- _init_ 也叫构造函数,创建对象时被调用,也可以省略。

-- self 变量绑定的是被创建的对象,名称可以随意。

  1. 创建对象(实例化)

变量 = 构造函数 (参数列表)

  1. 实例成员

  2. 实例变量

  1. 语法

  1. 定义:对象.变量名

  2. 调用:对象.变量名


  1. 说明

  1. 首次通过对象赋值为创建,再次赋值为修改.

w01 = Wife()

w01.name = “丽丽”

w01.name = “莉莉”

  1. 通常在构造函数(_init_)中创建。

w01 = Wife(“丽丽”,24)

print(w01.name)

  1. 每个对象存储一份,通过对象地址访问。


  1. 作用:描述某个对象的数据。

  2. __dict__:对象的属性,用于存储自身实例变量的字典。

  1. 实例方法

  1. 语法

(1) 定义: def 方法名称(self, 参数列表):

方法体

(2) 调用: 对象地址.实例方法名(参数列表)

不建议通过类名访问实例方法

  1. 说明

(1) 至少有一个形参,第一个参数绑定调用这个方法的对象,一般命名为"self"

(2) 无论创建多少对象,方法只有一份,并且被所有对象共享。

  1. 作用:表示对象行为。

  1. 类成员

  2. 类变量

  1. 语法

  1. 定义:在类中,方法外定义变量。

class 类名:

变量名 = 表达式

  1. 调用:类名.变量名

不建议通过对象访问类变量

  1. 说明

(1) 存储在类中。

(2) 只有一份,被所有对象共享。

  1. 作用:描述所有对象的共有数据。

  1. 类方法

  1. 语法

  1. 定义:

@classmethod

def 方法名称(cls,参数列表):

方法体

  1. 调用:类名.方法名(参数列表)

不建议通过对象访问类方法

  1. 说明

(1) 至少有一个形参,第一个形参用于绑定类,一般命名为'cls'

(2) 使用@classmethod修饰的目的是调用类方法时可以隐式传递类。

(3) 类方法中不能访问实例成员,实例方法中可以访问类成员。

  1. 作用:操作类变量。

  1. 静态方法

  1. 语法

  1. 定义:

@staticmethod

def 方法名称(参数列表):

方法体

  1. 调用:类名.方法名(参数列表)

不建议通过对象访问静态方法

  1. 说明

(1) 使用@ staticmethod修饰的目的是该方法不需要隐式传参数。

(2) 静态方法不能访问实例成员和类成员

  1. 作用:定义常用的工具函数。

  1. 三大特征

  2. 封装

  3. 数据角度讲

  1. 定义:

将一些基本数据类型复合成一个自定义类型。

  1. 优势:

将数据与对数据的操作相关联。

代码可读性更高(类是对象的模板)。

  1. 行为角度讲

  1. 定义:

类外提供必要的功能,隐藏实现的细节。

  1. 优势:

简化编程,使用者不必了解具体的实现细节,只需要调用对外提供的功能。

  1. 私有成员:

  1. 作用:无需向类外提供的成员,可以通过私有化进行屏蔽。

  2. 做法:命名使用双下划线开头。

  3. 本质:障眼法,实际也可以访问。

私有成员的名称被修改为:_类名__成员名,可以通过_dict_属性或dir函数查看。

  1. 属性@property

公开的实例变量,缺少逻辑验证。私有的实例变量与两个公开的方法相结合,又使调用者的操作略显复杂。而属性可以将两个方法的使用方式像操作变量一样方便。

  1. 定义:

@property

def 属性名(self):

return self.__属性名

@属性名.setter

def 属性名(self, value):

self.__属性名= value

  1. 调用:

对象.属性名 = 数据

变量 = 对象.属性名

  1. 说明:

通常两个公开的属性,保护一个私有的变量。

@property 负责读取,@属性名.setter 负责写入

只写:属性名= property(None, 写入方法名)

class Wife:
def __init__(self, name=None, weight=None):
self.name= name
self.weight=weight
def print_weight(self):
if self.weight>50:
print('你猜')
else:
print(self.weight)
def __fun01(self):
print('我不想说的事情')
w01 = Wife('芳芳',40)
# w01 = Wife('芳芳',80)
# w01.print_weight()
# w01.__fun01()  #不能调用私有成员
print(w01.__dict__)  #显示所有实例变量信息
'''
隐藏数据,限制
'''
class Wife:
def __init__(self, name=None, weight=None):
self.name = name
# self.__weight=weight   #被方法隐藏
self.set_weight(weight)
self.__weight
# 写入方法
def set_weight(self, value):
if 20 <= value <= 200:
self.__weight = value  # 隐藏在这个里
# {'name': '芳芳', '_Wife__weight': 40, 'weight': 900}
else:
raise Exception('我不要')
# 读取方法
def get_weight(self):
return self.__weight
w01 = Wife('芳芳', 40)
# w01.__fun01()  #不能调用私有成员
# w01.weight = 900
# print(w01.weight)
# 通过方法修改数据
# w01.set_weight(50)
# 通过方法获取数据
print(w01.get_weight())
# print(w01._Wife__weight())
print(w01.__dict__)  # 显示所有实例变量信息
"""
隐藏数据   通过方法隐藏数据
"""
class Wife:
def __init__(self, name="", weight=0):
self.name = name
# 如果不隐藏数据,外部可以任意操作.
# self.weight = weight
self.set_weight(weight)
# 写入方法
def set_weight(self,value):
if 20 <= value <=200:
self.__weight = value
else:
raise Exception("我不要")
# 读取方法
def get_weight(self):
return  self.__weight
w01 = Wife("芳芳", 40)
# w01.weight
# w01.__weight
# 通过方法修改数据
w01.set_weight(45)
# 通过方法获取数据
print(w01.get_weight())
print(w01.__dict__)
"""
隐藏数据  通过property隐藏数据property价值:将对实例的变量操作拦截下来(拦截)执行读和写
"""
class Wife:
def __init__(self, name="", weight1=0):
self.name = name
# 如果不隐藏数据,外部可以任意操作.
self.weight = weight1   #给了双下划线weight
# self.set_weight(weight)  #为了更直观数据,不用通过方法隐藏数据
# 写入方法
def set_weight(self,value):
if 20 <= value <=200:
self.__weight = value
else:
raise Exception("我不要")
# 读取方法
def get_weight(self):
return  self.__weight
# 类内方法外,类变量和实例变量一样,被类变量覆盖了实例变量;
# 1创建类变量,覆盖实例变量,名称相同
# weight= property(读取方法,写入方法)
# 2创建property对象property(读取方法,写入方法)这个地方只是获取方法执行,而不是返回值
weight1= property(get_weight,set_weight)  #*只是获取方法,而不是要返回值
w01 = Wife("芳芳", 40)
# w01.weight
# w01.__weight
# 通过方法修改数据
# w01.set_weight(45)
# 通过方法获取数据
# print(w01.get_weight())
# 3.通过类变量直接修改数据
w01.weight=45
print(w01.weight)
print(w01.__dict__)
"""
隐藏数据  通过property隐藏数据property价值:将对实例的变量操作拦截下来(拦截)执行读和写
"""
    隐藏数据 -- 通过property
    步骤:
        1. __init__方法中定义实例变量
        2. 使用@property修饰对象实例变量的读取方法
                注意:方法名与实例变量名相同
                     方法体返回私有变量
        3. 使用 @读取方法名.setter 修饰写入方法.
                注意:方法名与写入方法和实例变量名相同
                      方法体修改私有变量

    练习:exercise02py
"""
"""
class Wife:
def __init__(self, name="", weight1=0):
self.name = name
# 如果不隐藏数据,外部可以任意操作.
self.weight = weight1   #给了双下划线weight
# self.set_weight(weight)  #为了更直观数据,不用通过方法隐藏数据
# 创建p对象,绑定读取方法
@property  #weight=property(weight,none)
# 读取方法
def weight2(self):
return self.__weight
@weight2.setter    #读取方法名
# 写入方法'''
    练习:创建技能类(技能名称,冷却时间,攻击力度,消耗法力)
'''
class Attack:
    total_power=2000
    def __init__(self, name=None, attack=None, time=None, power=None):
        self.name = name
        self.attack = attack
        self.time=time
        self.power=power

    @property
    def name(self):
        return self.__name
    @name.setter
    def name(self,value):
        self.__name=value

    @property
    def time(self):
        return self.__time
    @time.setter
    def time(self,value):
        if 0 <= value <=120:
            self.__time = value
        else:
            raise Exception("我不要")

    @property
    def attack(self):
        return self.__attack
    @attack.setter
    def attack(self,value):
        if 0 <= value <= 200:
            self.__attack = value
        else:
            raise Exception("我不要")
    @property
    def power(self):
        return self.__power
    @power.setter
    def power(self,value):
        if -100 <= value <= 100:
            self.__power = value
            # Attack.total_power-=value
        else:
            raise Exception("我不要")
    def attack01(self):
        Attack.total_power-=self.attack
        print(self.name,self.time,self.attack,self.power,Attack.total_power)

w01=Attack('火影',40,80,50)
w01.time=80
print(w01.__dict__)
w01.attack01()
print(Attack.total_power)
# s01=Attack('九阳神功',110,90,76)
# print(s01.__dict__)
# print(Attack.total_power)
# s01.attack01()
def weight6(self,value):
if 20 <= value <=200:
self.__weight = value
else:
raise Exception("我不要")
# 类内方法外,类变量和实例变量一样,被类变量覆盖了实例变量;
# 1创建类变量,覆盖实例变量,名称相同
# weight= property(读取方法,写入方法)
# 2创建property对象property(读取方法,写入方法)这个地方只是获取方法执行,而不是返回值
# weight= property(get_weight,set_weight)  #*只是获取方法,而不是要返回值
w01 = Wife("芳芳", 40)
# w01.weight
# w01.__weight
# 通过方法修改数据
# w01.set_weight(45)
# 通过方法获取数据
# print(w01.get_weight())
# 3.通过类变量直接修改数据
w01.weight=61
print(w01.weight)
print(w01.__dict__)
print(w01.__dir__())
class Wife01:
def __init__(self, name="", weight=0):
self.name = name
# 如果不隐藏数据,外部可以任意操作.
# self.weight = weight   #给了双下划线weight
# self.set_weight(weight)  #为了更直观数据,不用通过方法隐藏数据
self.__weight=weight  #只能读不能写
# 创建p对象,绑定读取方法
# @property  #weight=property(weight,none)
# # 读取方法
# def weight(self):
#     # if 条件
#     return self.__weight #*10
# @weight.setter    #调动读取方法名
# 写入方法
#只能读的属性
def weight(self,value):
if 20 <= value <=200:
self.__weight = value
else:
raise Exception("我不要")
weight= property(None,weight)
w01=Wife01("小华",49)
w01.weight=30
print(w01.__dict__)
'''
定义敌人类  通过方法隐藏数据
'''
class Attack:
def __init__(self, name=None, attack=None):
self.name = name
# self.__weight=weight   #被方法隐藏
self.set_attack(attack)  #*重点在这个里
# 写入方法
def set_attack(self, value):
if 0 <= va'''
张无忌教赵敏九阳神功
赵敏教张无忌玉女心经
张无忌工作赚了5000
赵敏工作赚了10000
打印出每个人的技能和存款
'''

class Person:

    def __init__(self, name=None):
        self.name=name
        self.money=0
        self.skills=[]

    def teach(self,other,skill):
        other.skills.append(skill)
    def work(self,value):
        self.money+=value






zwj=Person('张无忌')
# w01.skill="九阳神功"
zm=Person('赵敏')
zwj.teach(zm,'九养生功')
lue <= 100:
self.__attack = value  # 隐藏在这个里
# {'name': '芳芳', '_Wife__weight': 40, 'weight': 900}
else:
raise Exception('我不要')
# 读取方法
def get_attack(self):
return self.__attack
w01 = Attack('芳芳', 60)
# w01.set_attack(120)
# w01.__fun01()  #不能调用私有成员
# w01.weight = 900
# print(w01.weight)
# 通过方法修改数据
# w01.set_weight(50)
# 通过方法获取数据
print(w01.get_attack())
# print(w01._Attack__attack())
print(w01.__dict__)  # 显示所有实例变量信息
'''
定义敌人类   通过property隐藏数据
'''
class Attack:
def __init__(self, name=None, attack1=None):
self.name = name
self.attack = attack1  # 被方法隐藏
# self.set_attack(attack)  #*重点在这个里
@property  # weight=property(weight,none)
# 读取方法
def get_attack(self):
return self.__attack
@get_attack.setter
# 写入方法
def set_attack(self, value):
if 0 <= value <= 100:
self.__attack = value  # 隐藏在这个里
# {'name': '芳芳', '_Wife__weight': 40, 'weight': 900}
else:
raise Exception('我不要')
# weight1 = property(get_attack, set_attack)
w01 = Attack('芳芳', 60)
w01.attack = 86
# w01.set_attack(120)
# w01.__fun01()  #不能调用私有成员
# w01.weight = 900
# print(w01.weight)
# 通过方法修改数据
# w01.set_weight(50)
# 通过方法获取数据
print(w01.attack)
# print(w01._Attack__attack())
print(w01.__dict__)  # 显示所有实例变量信息
'''
练习:创建技能类(技能名称,冷却时间,攻击力度,消耗法力)
'''
class Attack:
total_power=2000
def __init__(self, name=None, attack=None, time=None, power=None):
self.name = name
self.attack = attack
self.time=time
self.power=power
@property
def name(self):
return self.__name
@name.setter
def name(self,value):
self.__name=value
@property
def time(self):
return self.__time
@time.setter
def time(self,value):
if 0 <= value <=120:
self.__time = value
else:
raise Exception("我不要")
@property
def attack(self):
return self.__attack
@attack.setter
def attack(self,value):
if 0 <= value <= 200:
self.__attack = value
else:
raise Exception("我不要")
@property
def power(self):
return self.__power
@power.setter
def power(self,value):
if -100 <= value <= 100:
self.__power = value
# Attack.total_power-=value
else:
raise Exception("我不要")
def attack01(self):
Attack.total_power-=self.attack
print(self.name,self.time,self.attack,self.power,Attack.total_power)
w01=Attack('火影',40,80,50)
w01.time=80
print(w01.__dict__)
w01.attack01()
print(Attack.total_power)
# s01=Attack('九阳神功',110,90,76)
# print(s01.__dict__)
# print(Attack.total_power)
# s01.attack01()
'''
小明在银行取钱
钱多了  钱少了
'''
class Person:
'''
'''
def __init__(self,name,money):
self.name=name
self.money=money
class Bank:
def __init__(self,name,total_money,person):
self.name=name
self.total_money=total_money
self.person=person
def take_monye(self):
if self.total_money>=self.person.money:
print('共计有',self.total_money)
self.total_money-=self.person.money
print(self.person.name,'取走了',self.person.money,self.name,'剩余有',self.total_money,)
else:
print('金额不足')
w01=Person('小明',3500)
s01=Bank('招商银行',20000,w01)
s01.take_monye()
class Wife01:
def __init__(self, name="", weight=0):
self.name = name
# 如果不隐藏数据,外部可以任意操作.
# self.weight = weight   #给了双下划线weight
# self.set_weight(weight)  #为了更直观数据,不用通过方法隐藏数据
self.__weight=weight  #只能读不能写
# 创建p对象,绑定读取方法
# @property  #weight=property(weight,none)
# # 读取方法
# def weight(self):
#     # if 条件
#     return self.__weight #*10
# @weight.setter    #调动读取方法名
# 写入方法
#只能读的属性
def weight(self,value):
if 20 <= value <=200:
self.__weight = value
else:
raise Exception("我不要")
weight= property(None,weight)
w01=Wife01("小华",49)
w01.weight=30
print(w01.__dict__)
'''
封装---设计角度   一个类调用另一个类
'''
# 需求:以面向对象的思想,描述一下情景
# 老张开车去东北
class Person:
def __init__(self, name=None, car=None):  # 对象数据
self.name = name
# self.car=Car()   #创造我的车
self.tool = car  # 抽象它   我可以使用不同交通工具
def go_to(self):  # 对象的行为方法
print(self.name)
# Car().run()   #Car()创建对象
self.tool.run()  # 去哪里都是一辆新车
print('去东北')  # 去哪里都是我的那辆车
def go_home(self):
self.tool.run()   #调用Car.run()
print('回家')
# 需要调用实例成员(实例)
class Car:
def run(self):
print('开车走你...')
bm = Car()
lz = Person('老张', bm)
lz.go_to()
# lz.go_home()


  1. 设计角度讲

  1. 定义:

(1) 分而治之

将一个大的需求分解为许多类,每个类处理一个独立的功能。

(2) 变则疏之

变化的地方独立封装,避免影响其他类。

(3) 高 内 聚

类中各个方法都在完成一项任务(单一职责的类)

(4) 低 耦 合

类与类的关联性与依赖度要低(每个类独立),让一个类的改变,尽少影响其他类。

  1. 优势:

便于分工,便于复用,可扩展性强。


  1. **类有行为,对象有数据

类与类行为不同

对象与对象数据不同

分后合,类与类互相调用

  1. 案例:信息管理系统

 

  1. 需求

实现对学生信息的增加、删除、修改和查询。

  1. 分析

界面可能使用控制台,也可能使用Web等等。

  1. 识别对象:界面视图类 逻辑控制类 数据模型类


  1. 分配职责:

界面视图类:负责处理界面逻辑,比如显示菜单,获取输入,显示结果等。

逻辑控制类:负责存储学生信息,处理业务逻辑。比如添加、删除等

数据模型类:定义需要处理的数据类型。比如学生信息。


  1. 建立交互:

界面视图对象 <----> 数据模型对象 <----> 逻辑控制对象

  1. 设计

数据模型类:StudentModel

数据:编号 id,姓名 name,年龄 age,成绩 score

逻辑控制类:StudentManagerController

数据:学生列表 __stu_list

行为:获取列表 stu_list,添加学生 add_student,删除学生remove_student,修改学生update_student,根据成绩排序order_by_score

界面视图类:StudentManagerView

数据:逻辑控制对象__manager

行为:显示菜单__display_menu,选择菜单项__select_menu_item,入口逻辑main

输入学生__input_students,输出学生__output_students,删除学生__delete_student,修改学生信息__modify_student

  1. 继承

老张开车,手雷,图形面积

,把儿子抽象化为父亲

儿子是对象,对象行为(对象方法)共性就到父亲(:抽象出来的)(父亲,儿子对象方法,共性)

在闭区间中用:人类:的行为def:()

多态:重写

开闭原则:增加新的交通工具,不影响人类

依赖倒置:人类调用交通工具(调用大范围的东东,包含万物的,回本不动),而不调用汽车,飞机

  1. 语法角度讲

  2. 继承方法
  1. 代码:

class 父类:

def 父类方法(self):

方法体


class 子类(父类)

def 子类方法(self):

方法体


儿子 = 子类()

儿子.子类方法()

儿子.父类方法()


  1. 说明:

子类直接拥有父类的方法.

  1. 内置函数

isinstance(对象, 类型)

返回指定对象是否是某个类的对象。

issubclass(类型,类型)

返回指定类型是否属于某个类型。

  1. 继承数据
  1. 代码

class 子类(父类):

def __init__(self,参数列表):

super().__init__(参数列表)

self.自身实例变量 = 参数

  1. 说明

子类如果没有构造函数,将自动执行父类的,但如果有构造函数将覆盖父类的。此时必须通过super()函数调用父类的构造函数,以确保父类实例变量被正常创建。

  1. 定义

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

说明:子类直接具有父类的成员(共性),还可以扩展新功能。

  1. 优点

一种代码复用的方式。

  1. 缺点

耦合度高:父类的变化,直接影响子类。

class Animal:
def eat(self):
print('')
class Dog(Animal):
def run(self):
print("")
class Bird(Animal):
def fly(self):
print('')
bird01 = Bird()
bird01.fly()
bird01.eat()
a01 = Animal()
a01.eat()
dog= Dog()
# 狗对象 是一种  动物类型
print(isinstance(dog,Animal))
# 狗对象 是一种  狗类型
print(isinstance(dog,Dog))
print(isinstance(a01,Dog))
print(issubclass(Dog,Animal))
print(issubclass(Bird,Animal))
# 狗对象 是 狗类型
print(type(dog)==Dog)
# 狗对象 不是 动物类型
print(type(dog)==Animal)


  1. 设计角度讲

  2. 定义

将相关类的共性进行抽象,统一概念,隔离变化。

  1. 适用性

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

  1. 相关概念

父类(基类、超类)、子类(派生类)。

父类相对于子类更抽象,范围更宽泛;子类相对于父类更具体,范围更狭小。

单继承:父类只有一个(例如 JavaC#)。

多继承:父类有多个(例如C++Python)。

Object类:任何类都直接或间接继承自 object 类。

  1. 多继承(隔离变化)

一个子类继承两个或两个以上的基类,父类中的属性和方法同时被子类继承下来。

同名方法的解析顺序(MROMethod Resolution Order:

类自身 --> 父类继承列表(由左至右)--> 再上层父类

人 去 交通工具 汽车

手雷 炸 交通工具 汽车

通过类名调用实例方法:B.m01(self)

A

/ \

/ \

B C

\ /

\ /

D

  1. 多态

  2. 设计角度讲

  3. 定义

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

  1. 作用
  1. 在继承的基础上,体现类型的个性化(一个行为有不同的实现)。

  2. 增强程序扩展性,体现开闭原则。

  1. 语法角度讲

  2. 重写

子类实现了父类中相同的方法(方法名、参数)。

在调用该方法时,实际执行的是子类的方法。

  1. 快捷键

Ctrl + O

  1. 内置可重写函数

Python中,以双下划线开头、双下划线结尾的是系统定义的成员。我们可以在自定义类中进行重写,从而改变其行为。

  1. 转换字符串

__str__函数:将对象转换为字符串(对人友好的)

__repr__函数:将对象转换为字符串(解释器可识别的)

  1. 运算符重载

定义:让自定义的类生成的对象(实例)能够使用运算符进行操作。

  1. 算数运算符

 

  1. 反向算数运算符重载

 

  1. 复合运算符重载

 

  1. 比较运算重载

 

  1. 设计原则

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

Open Closed Principle

对扩展开放,对修改关闭。

增加新功能,不改变原有代码。

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

Single Responsibility Principle

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

  1. 依赖倒置(依赖抽象)

Dependency Inversion Principle

客户端代码(调用的类)尽量依赖(使用)抽象。

抽象不应该依赖细节,细节应该依赖抽象。

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

Composite Reuse Principle

如果仅仅为了代码复用优先选择组合复用,而非继承复用。

组合的耦合性相对继承低。

  1. 里氏替换(继承后的重写,指导继承的设计)

Liskov Substitution Principle

父类出现的地方可以被子类替换,在替换后依然保持原功能。

子类要拥有父类的所有功能。

子类在重写父类方法时,尽量选择扩展重写,防止改变了功能。

  1. 迪米特法则(类与类交互的原则)

Law of Demeter

不要和陌生人说话。

类与类交互时,在满足功能要求的基础上,传递的数据量越少越好。因为这样可能降低耦合度。

低耦合 〔V 掉用 C 一直交互,如何低耦合?找一个中间的 做爹法
















'''
day13  复习
面向对象:考虑问题从对象的角度出的发,谁 干嘛?
抽象:对象--> 
子类1 汽车 子类2 轮船---> 父类(子类中的共性的)交通工具
哲学上的概念:抽象的概念!
从多个事物中,舍弃个性(非本质的)特征.
抽出共性的的本质的过程:


三大特征:变化了怎么办?
封装:
语法:  用类将多个数据,与对数据的操作整合为一个类型:
class 类名:
def __init__(self,参数列表):
self.数据1 = 参数
def 对象的数据操作(self):
方法体
变量=类名(参数)
设计:   :活字印刷, 分而治之,变则疏之(行为方法不一样)变化点 飞机 火车...  行业特征:哪里有地方变化
高内聚,低耦合(类之间的变化,影响尽量小) 人调用火车紧耦合  人调用交通工具(隔离)得益于继承
继承:(由分到合)  抽象出多个子类的共性(火车类,飞机类  共性:交通工具类  共同的行为方法:运输())
语法: 继承方法:子类直接可以使用父类方法
继承数据:
子类没有构造函数__init__使用父类的
子类有构造函数,则需要调用父类构造函数super().__init_()
class 父类:
def __init__(self,爸爸的参数):
self.爸爸的数据=爸爸参数
(方法行为)
class 子类(父类):
def __init__(self, 爸爸的参数,儿子参数)
super().__init_(爸爸的参数)
self.儿子的数据= 儿子的参数
设计: 抽象变化,隔离变化
继承方法:
class 父类:
def 父类对象的数据操作(self,爸爸的参数):
self.爸爸的数据=爸爸参数
(方法行为)
class 子类(父类):
def __init__(self, 爸爸的参数,儿子参数)
super().__init_(爸爸的参数)
self.儿子的数据= 儿子的参数
多态:
语法:调用父类方法,在不同子类上执行效果不同
class 父类:
def 功能1(self):
...
class 子类(父类):
# 3 .子类重写
def  功能1(self)
...
变量=父类()
变量,功能1() 不是多态
变量=子类()
变量,功能1() 不是多态

def 函数(父类型参数):
#1 .调用父类方法
父类型参数.功能1()
#2 . 传递不同的子类对象
函数(子类())
直接调儿子,把代码写死了 不灵活
以不变应万变
设计:增加程序的灵活度(子类替换父类自行不同逻辑)
设计原则:封装,继承,多态 的指导(粗化)
六大原则:
1.开闭原则:可以增加新功能,不能允许修改客户端代码(调用方).
2.类的单一职责(一个类的定义 一个函数也一个功能, 火车,而不是运输),一个类有且只有一个改变它的原因
3.依赖倒置 调用父类,不调用子(因为子是变化的); 客户端代码(调用的类)尽量依赖(使用)抽象
抽象不依赖细节,细节依赖抽像
4.组合复用原则:组合复用,非继承复用(就两用复用)
class A:
def a(self):
print("a")
class B(A):
def b(self):
print("b")
# 继承复用
super().a()
b01 = B()
b01.b()
优点:直接使用,简单省事
缺点:紧耦合
一块内存,破坏了封装性,
耦合太高 父类变化,子影响
设计原则:组合复用
组合是类与类之间的关系
通过变量调用,而不是通过继承复用


'''
'''
练习题
定义员工管理器
1,记录所有员工
2,提供计算总工资的方法
员工种类:
程序员:底薪+项目分红
测试员:底薪_bug*5
...
要求:增加新员工种类,不影响员工管理器
体会:继承与组合
'''
class PersonnelManager:
def __init__(self):
self.__per_list=[]
def add_per(self,per_target):
self.__per_list.append(per_target)
def total_per(self):
count = 0
for item in self.__per_list:
count +=item.account()
return count
class Fu:
def __init__(self,dixin):
self.dixin=dixin
def account(self):
return self.dixin
class Son1(Fu):
def __init__(self,dixin, fenhong):
super().__init__(dixin)
self.fenhong = fenhong
def account(self):
return super().account()+self.fenhong #里氏替换
class Son2(Fu):
def __init__(self,dixin,bug ):
super().__init__(dixin)
self.bug=bug
def account(self):
return self.dixin+self.bug*5
p01 =PersonnelManager()
s01 = Son1(5000,8000)
s02 = Son2(3000,40)
p01.add_per(s01)
p01.add_per(s02)
print(p01.total_per())




























































posted @ 2019-09-18 20:28  晓亮86  阅读(396)  评论(0)    收藏  举报