对象已找到,但事情还没有结束。为了让你充分的感受 小Python 中对象的魅力,就需要了解其三大特性 封装、继承、多态

1. 封装

面向对象的第一个特性 —— 封装(英语:encapsulation),从字面上来理解就是包装的意思,专业点就是信息隐藏,是指利用抽象数据类型将数据和基于数据的操作封装在一起,使其构成一个不可分割的独立实体,数据被保护在抽象数据类型的内部,尽可能地隐藏内部的细节,只保留一些对外接口使之与外部发生联系。

对于封装而言,一个对象它所封装的是自己的属性和方法,所以它是不需要依赖其他对象就可以完成自己的操作。使用封装有三大好处:

  • 良好的封装能够减少耦合。
  • 类内部的结构可以自由修改。
  • 可以对成员进行更精确的控制。
  • 隐藏信息,实现细节。

封装把一个对象的属性私有化,同时提供一些可以被外界访问的属性的方法,如果不想被外界方法,我们大可不必提供方法给外界访问。但是如果一个类没有提供给外界访问的方法,那么这个类也没有什么意义了。

通俗的解释就是:非礼勿视,非礼勿听,非礼勿言,非礼勿动。

91.jpg

"""
    文件名:oop_encapsulation.py
    用途:通过模拟 注册过程,个人中心 演示 封装 的特性
    场景描述:当在某站点注册完账号后,就创建了一个站点用户(对象),而当我们需要修改个人信息时,
             有些信息是可再修改的,而有些信息时不允许再修改的,甚至不允许暴露出去的。
    作者:Mr.潘
"""

# Python 中没有强制性的封装特性,提供了三种级别的访问机制
#     公开访问:属性和方法 以字母开头命名,外界可以随意访问,类似公开约束
#     项目级私有化:属性和方法 以单个 _ 开头命名,但外界依然可以访问,类似于道德约束
#     强制私有化:属性和方法 以两个 _ 开头命名,外界不允许访问,但依然可以通过特殊途径访问,类似于法律约束

class SystemUser:
    def __init__(self, account, password):
        """创建系统用户"""
        self._account = account        # 帐号一旦创建,不可再次修改
        self._password = password      # 密码可修改,但不可以直接访问
        self.nick_name = '无名氏'      # 注册是不需要提供,可公开访问修改
        self._gender = '男'            # 注册是不需要提供,但拥有默认值,也可以被二次修改,但只能修改为 '男' 或 '女'

    def get_account(self):
        """对外暴露一个只能访问的方法"""
        return self._account

    def set_password(self, old_password, password):
        """对外暴露一个只能修改的方法"""
        if old_password == self._password:
            self._password = password
        else:
            print("原始密码不匹配,修改密码失败。")

    def get_gender(self):
        """对外暴露一个能访问的方法"""
        return self._gender

    def set_gender(self, gender):
        """对外暴露一个能修改的方法,且限制只能被修改为 '男' 或 '女'"""
        if gender in ('男', '女'):
            self._gender = gender
        else:
            print("性别只能是男或者女,非人类的性别。")

    def introduction(self):
        """自我介绍"""
        print("大家好,我叫 {},我的这个方法可以被公开调用。".format(self.nick_name))


# 测试
pansf = SystemUser("pansf", "123456")
print(pansf._account)        # 可访问,但属于违反项目规范的访问修改约束,丢弃
print(pansf.get_account())   # 利用暴露的公开方法访问,是正道

pansf.set_password("123456", '000000')

pansf.nick_name = "Mr.潘"    # 公开的属性,可以被直接访问修改

print(pansf.get_gender())    # 创建用户时,并未要求提供 性别,但创建成功后可再次修改
pansf.set_gender('男')       # 只能设置 '男' 或者 '女'

pansf.introduction()         # 公开的方法,可以被直接访问

2. 继承

面向对象的第二个特性 —— 继承(英语:inheritance),是面向对象软件技术当中的一个概念。如果一个类别B“继承自”另一个类别A,就把这个B称为“A的子类”,而把A称为“B的父类别”也可以称“A是B的超类”。继承可以使得子类具有父类别的各种属性和方法,而不需要再次编写相同的代码。在令子类别继承父类别的同时,可以重新定义某些属性,并重写某些方法,即覆盖父类别的原有属性和方法,使其获得与父类别不同的功能。另外,为子类追加新的属性和方法也是常见的做法。

通俗的解释就是:龙生龙,凤生凤,老鼠儿子会打洞,青出于蓝而胜于蓝。

92.png

'''
@File    :   mock_no_inheritance.py
@Time    :   2020/08/27
@Author  :   Mr.潘
@Desc    :   在没有使用 继承 的情况下,遗传体现
@Desc    :   助力软件测试行业,邀请你身边的小伙伴,共同加入软件行业,敬请找我!成为我的口碑学员,终生技术支持!
@Contact :   email: pansfy@163.com , QQ: 1246928388
@License :   (C)Copyright 2020-2021, http://pansaifei.com
'''

class MouseFather:
    # 鼠爸爸
    def __init__(self, name):
        """创建实例的方法"""
        self.name = name

    def dig_hole(self):
        """鼠爸爸挖洞的能力"""
        print("地下打洞谁最强,来个老鼠称霸王。")

class MouseSon:
    # 鼠儿子
    def __init__(self, name):
        """创建实例的方法"""
        self.name = name

    def dig_hole(self):
        """鼠儿子挖洞的能力"""
        print("地下打洞谁最强,来个老鼠称霸王。")

    def driver_tank(self):
        """鼠儿子的特殊技能"""
        print("我有坦克我怕谁,嘟嘟嘟...")
'''
@File    :   mock_inheritance.py
@Time    :   2020/08/27
@Author  :   Mr.潘
@Desc    :   在 继承 的情况下,遗传体现
@Desc    :   助力软件测试行业,邀请你身边的小伙伴,共同加入软件行业,敬请找我!成为我的口碑学员,终生技术支持!
@Contact :   email: pansfy@163.com , QQ: 1246928388
@License :   (C)Copyright 2020-2021, http://pansaifei.com
'''

class MouseFather:
    # 鼠爸爸
    def __init__(self, name):
        """创建实例的方法"""
        self.name = name

    def dig_hole(self):
        """鼠爸爸挖洞的能力"""
        print("地下打洞谁最强,来个老鼠称霸王。")

class MouseSon(MouseFather):
    # 鼠儿子

    def driver_tank(self):
        """鼠儿子的特殊技能"""
        print("我有坦克我怕谁,嘟嘟嘟...")


father = MouseFather("鼠爸")
father.dig_hole()           # 鼠爸的能力,调用自己的

shuke = MouseSon("鼠儿子")   
shuke.dig_hole()            # 鼠爸的能力,我是鼠爸的儿子,我也拥有这个能力,调用鼠爸的(老鼠的儿子会打洞)
shuke.driver_tank()         # 我比鼠爸更强,我拥有更多的能力,调用自己的(青出于蓝而胜于蓝)

总结:如果多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那个类即可。父类又称基类,超类;子类又称派生类。子类可以直接访问父类中的非私有的属性和行为。小Python 支持多继承,格式如下:子类(父类1, 父类2, 父类3, ...),好处博客们自行思考。

3. 多态

面向对象的第三个特性 —— 多态(英文:polymorphism)。在讨论 小Python 的多态技术之前,我们先来看一下这个词原本的涵义:多态这个词实际上可以划分成两个单独的希腊字母根。第一个就是 Poly,就是多于一个的意思。下一个就是 Morph,它是指具有多种形态。因此,在某种抽象层面上,我们可以假设多态是指处于具有多种类型的对象平行线上的东西;在软件层面上,我们可以认为这是一种使用单个通用接口来操作具有相似特性数据的能力。

通俗的解释就是:龙生九子,子子不同。

93.jpg

'''
@File    :   mock_polymorphism.py
@Time    :   2020/08/29
@Author  :   Mr.潘
@Desc    :   通过 龙生九子,子子不同 来模拟多态
@Desc    :   助力软件测试行业,邀请你身边的小伙伴,共同加入软件行业,敬请找我!成为我的口碑学员,终生技术支持!
@Contact :   手机/微信:18550208315, 邮箱: pansfy@163.com
@License :   (C)Copyright 2020-2021, http://pansaifei.com
'''

"""
【出处】:《中国吉祥图说》
1.长子囚牛,喜音乐,蹲立于琴头;
2.次子睚眦(yá zì),嗜杀喜斗,刻镂于刀环、剑柄吞口,心胸狭隘;
3.三子嘲风,形似兽,是老三,平生好险又好望,殿台角上的走兽是它的遗像。也有人一直认为它是有着龙脉的凤。
4.四子蒲牢,受击就大声吼叫,充作洪钟提梁的兽钮,助其鸣声远扬;
5.五子狻猊(Suān ní),形似狮子,排行第五,平生喜静不喜动,好坐,又喜欢烟火,因此佛座上和香炉上的脚部装饰就是它的遗像。
6.六子霸下(也有另一种名字,方框内的看成一个字,[虫八][虫夏]),又名赑屃(bì xì),似龟有齿,喜欢负重,是碑下龟;
7.七子狴犴(bì àn),形似虎好讼,狱门或官衙正堂两侧有其像;
8.八子负屃(fùxì),身似龙,雅好斯文,盘绕在石碑头顶;
9.九子螭吻(chī wěn),又名鸱尾或鸱(chī)吻,口润嗓粗而好吞,遂成殿脊两端的吞脊兽,取其灭火消灾。
"""
class Dragon:
    def __init__(self, name):
        """实例化方法"""
        self._name = name
  
    def introduce(self):
        """自我介绍"""
        print("大家好,我是老龙王...")

class EldestSon(Dragon):
    def introduce(self):
        """长子特色"""
        print("我是{},喜音乐,蹲立于琴头".format(self._name))

class SecondSon(Dragon):
    def introduce(self):
        """次子特色"""
        print("我是{},嗜杀喜斗,刻镂于刀环、剑柄吞口,心胸狭隘".format(self._name))

class ThridSon(Dragon):
    def introduce(self):
        """三子特色"""
        print("我是{},平生好险又好望,殿台角上的走兽是它的遗像".format(self._name))


qiuniu = EldestSon("囚牛")
yazi = SecondSon("睚眦")
chaofeng = ThridSon("嘲风")

qiuniu.introduce(qiuniu)       	# 长子的特色
yazi.introduce(yazi)         	# 次子特色
chaofeng.introduce(chaofeng)	# 三子特色