zoukankan      html  css  js  c++  java
  • 第三十二篇 面向对象三大特性之封装

    什么是封装?

    先抛开面向对象,单单去想什么是装,装就是找一个麻袋,把你喜欢的,不喜欢的,小猫,小狗,小鸡等等都装进麻袋里,这就是装。---对应到面向对象里,这个麻袋就是 类 或者 对象,类 或者 对象里(装的过程)定义的数据属性和函数属性就好比麻袋里的小猫,小狗。对类来说有自己的属性字典,对实例(对象)来说也有自己的属性字典,而这些方法,属性都存在了(装到了)各自的属性字典里去了。

    而封,就是把麻袋口系上。---对应到面向对象里,封的概念代表隐藏。

    封装合起来理解:就是把内容封起来,外部人看到的只有类名(麻袋),里面具体的方法,属性(小猫小狗)他是看不到的,就实现了隐藏的目的。

    封装的本质,是要明确的区分内外 。

    class People:
        def __init__(self, idnumber, name, age, salary):
            self.idnumber = idnumber
            self.name = name
            self.age = age
            self.salary = salary
    
        def get_id(self):
            print("你现在找到的是[%s]的身份证号:%s" %(self.name, self.idnumber))
    
    
    if __name__ == '__main__':
        print(People.__dict__)
        p1 = People('34114134134314134134','小黄','24', '30000')
        p1.get_id()
    示例1:People类

    封装的第一层意义:

    有上面一个People类,存在a.py文件里,此时在b.py文件里,去导入(import a),然后实例化,调用,等操作,这也是一种封装。实现了隐藏

    from a import People
    
    p2 = People('34114134432140980893','小黑','22', '10000')
    p2.get_id()
    封装的第一层意思:导入到另一文件使用

    然后,封装远远不止这一层意思这么简单。

    封装的第二层的封装:类中定义私有的,只在类内部使用,外部无法访问

    和几个特性:

    Python当中的定义的语言约定,这个约定并不是真正的限制,而是定义者和调用者达成的一种默契。

    约定一: 单下划线开头:任何以单下划线开头的名字都应该是内部的,私有的。

    属性名以单下划线开头,就是把数据隐藏在内部,不让外部看到。

    这么做的目的,就是在调用者调的时候,只有看到是单下划线开头的,调用者就应该知道,这是内部属性,你需要知趣的不要再去调用了

    class People:
        # 单下划线开头的属性
        _star = 'from earth'
        def __init__(self, idnumber, name, age, salary):
            self.idnumber = idnumber
            self.name = name
            self.age = age
            self.salary = salary
    
        def get_id(self):
            print("你现在找到的是[%s]的身份证号:%s" %(self.name, self.idnumber))
    
    
    if __name__ == '__main__':
        p1 = People('34114134134314134134','小黄','24', '30000')
         # 调用单下划线的属性,实际上是可以调用的到的。然而,根据Python语言的约定,作为使用者,你就不应该去调用了。
        print(p1._star)   # from earth

    上面的示例,让一脸茫然的我,还需要另一个解释,都说了是私有的,怎么还能被外部访问。记住这个解释:

    这只是一种约定,Python并不会真正的阻止你访问私有属性,模块也遵循这种约定,如果模块名以单下划线开头,那么 from moudle import时是不能被导入的。

    但是你from module import _private_module 依然可以导入的哦。

    其实很多时候,你去调用一个模块的功能的时候回遇到单下划线开头的(socket._socket.sys._home, sys._home, sys._clear_type_cache)这些都是私有的,原则上是只供内部调用的,作为外部的你,一意孤行也是可以用的,只不过会遭到同行的鄙视。

    约定二: 双下划线开头的属性。

    class People:
        # 双下划线属性
        # 只要是__开头的属性,Python都会自动做一个重命名的操作,命名为:_类名__属性名
        __star = 'from earth double line'
        def __init__(self, idnumber, name, age, salary):
            self.idnumber = idnumber
            self.name = name
            self.age = age
            self.salary = salary
    
        def get_id(self):
            print("你现在找到的是[%s]的身份证号:%s" %(self.name, self.idnumber))
    
    
    if __name__ == '__main__':
        print(People.__dict__)
        #结果
        '''
        {'__module__': '__main__', '_People__star': 'from earth double line', '__init__': <function People.__init__ at 0x105071730>, 
        'get_id': <function People.get_id at 0x1050717b8>, '__dict__': <attribute '__dict__' of 'People' objects>, 
        '__weakref__': <attribute '__weakref__' of 'People' objects>, '__doc__': None}
        '''
        p1 = People('34114134134314134134','小黄','24', '30000')
        # 直接调用双下划线的属性,这个角度是调用不到了,看着是是实现了隐藏的目的。
        # print(p1.__star)   
        # AttributeError: 'People' object has no attribute '__star'
        # 换个方法调用,却能够调用的到
        print(p1._People__star)  # from earth double line
    
        # 这是为什么?
        '''
        原来,从类的字典属性里可以看到,Python对以双下划线开头的属性,都进行的重命名,命名规则是:_类名__属性名。
        所以,用重命名的属性名,当然就可以调用的到了
        '''

     第三个层面的封装,才是真正意义上的封装。明确区分内外,内部的去实现逻辑,外部的无法知晓,并且为封装到内部的逻辑提供一个访问接口给外部使用(这才是真正的封装,具体实现,会在面向对象进阶中讲,听着好高级的样子哦)

    总结:

    上面提到的两种不同的编码约定(单下划线和双下划线)来命名私有属性,那么问题来了:到底哪种方式好呢?

    大多数情况下,你应该让你的非公共名称以单下划线开头,但是,如果你清楚你的代码会涉及到子类,并且有些内部属性应该在子类中隐藏起来,那么菜考虑使用双下划线方案。但是无论哪种方案,其实Python都没有从根本上限制你的访问。

    说了半天,好像在说废话,得出的结论是:不可能完成真正的封装。没错,这不是你的错,也不是我的错,哈哈。是Python的错。

  • 相关阅读:
    java获取年份的后两位
    jdbcTemplate的Dao层封装
    beta准备
    福大软工 · 第十一次作业
    Alpha 冲刺 (10/10)
    Alpha 冲刺 (9/10)
    Alpha 冲刺 (8/10)
    Alpha 冲刺 (7/10)
    Alpha 冲刺 (6/10)
    Alpha 冲刺 (5/10)
  • 原文地址:https://www.cnblogs.com/victorm/p/9326440.html
Copyright © 2011-2022 走看看