zoukankan      html  css  js  c++  java
  • 面向对象【林老师版】:封装-如何隐藏?(十四)

    一、引子

    从封装本身的意思去理解,封装就好像是拿来一个麻袋,把小猫,小狗,小王八,还有alex一起装进麻袋,然后把麻袋封上口子。照这种逻辑看,封装=‘隐藏’,这种理解是相当片面的

    在python中用双下划线开头的方式将属性隐藏起来(设置成私有的)

    1、代码

    class A:
        __x=1 #_A__x=1
    
        def __init__(self,name):
            self.__name=name #self._A__name=name
    
        def __foo(self): #def _A__foo(self):
            print('run foo')
    
    
    print(A.__dict__)
    

    二、自动变形的特点

    1、这仅仅这是一种变形操作

    1、代码

    print(A.__dict__)

    2、打印输出

    {'__module__': '__main__', '_A__x': 1, '__dict__': <attribute '__dict__' of 'A' objects>, '__init__': <function A.__init__ at 0x0000000000B92378>, '__doc__': None, '_A__foo': <function A.__foo at 0x0000000000B92400>, '__weakref__': <attribute '__weakref__' of 'A' objects>}
    
    类中所有双下划线开头的名称如__x都会自动变形成:_类名__x的形式

    2、在类内部是可以直接使用:obj.__AttrName

     1、代码

    
    
    a=A('egon')
    print(a.__dict__)
    
    
    

    2、打印结果

    
    
    {'_A__name': 'egon'}
    
    
    
    类中定义的__x只能在内部使用,如self.__x,引用的就是变形的结果。

    3、在类外部无法直接obj.__AttrName

    1、打印类的属性代码

    1、代码

    print(A.__x)
    

    2、打印输出

    Traceback (most recent call last):
      File "F:/s13/day07/17 如何实现属性的隐藏.py", line 11, in <module>
        print(A.__x)
    AttributeError: type object 'A' has no attribute '__x'
    

    2、打印对象的属性

    1、代码

    print(A.__foo)
    

    2、打印输出结果

    Traceback (most recent call last):
      File "F:/s13/day07/17 如何实现属性的隐藏.py", line 12, in <module>
        print(A.__foo)
    AttributeError: type object 'A' has no attribute '__foo'
    

    这种变形其实正是针对外部的变形,在外部是无法通过__x这个名字访问到的

    4、子类无法覆盖父类__开头的属性

    1、代码

        def bar(self):
            self.__foo() #self._A__foo()
            print('from bar')
    
    a=A('egon')
    a.bar()
    

    2、输出结果

    run foo
    from bar
    

    在子类定义的__x不会覆盖在父类定义的__x,因为子类中变形成了:_子类名__x,而父类中变形成了:_父类名__x,即双下滑线开头的属性在继承给子类时,子类是无法覆盖的

    1、代码

    a=A('egon')
    a._A__foo()
    a._A__x
    
    #print(a.__name) #a.__dict__['__name']
    print(a.__dict__)
    

    2、打印输出结果

    run foo
    {'_A__name': 'egon'}

    5、最终总结注释

    #其实这仅仅这是一种变形操作
    #类中所有双下划线开头的名称如__x都会自动变形成:_类名__x的形式:
    
    class A:
        __N=0 #类的数据属性就应该是共享的,但是语法上是可以把类的数据属性设置成私有的如__N,会变形为_A__N
        def __init__(self):
            self.__X=10 #变形为self._A__X
        def __foo(self): #变形为_A__foo
            print('from A')
        def bar(self):
            self.__foo() #只有在类内部才可以通过__foo的形式访问到.
    
    #A._A__N是可以访问到的,即这种操作并不是严格意义上的限制外部访问,仅仅只是一种语法意义上的变形

    三、变形需要注意的问题

    1、外部直接访问属性

    1、代码

    class Foo:
        def __func(self): #_Foo__func
            print('from foo')
    
    class Bar(Foo):
        def __func(self): #_Bar__func
            print('from bar')
    
    
    class B:
        __x=1
    
        def __init__(self,name):
            self.__name=name #self._B__name=name
    
    
    print(B._B__x)
    

    2、打印输出

    1
    

    这种机制也并没有真正意义上限制我们从外部直接访问属性,知道了类名和属性名就可以拼出名字:_类名__属性,然后就可以访问了,如a._A__N

    2、变形的过程只在类的定义时发生一次

    1、代码

    B.__y=2
    print(B.__dict__)
    b=B('egon')
    print(b.__dict__)
    
    b.__age=18
    print(b.__dict__)
    print(b.__age)

    2、打印输出

    {'__module__': '__main__', '__y': 2, '__doc__': None, '_B__x': 1, '__dict__': <attribute '__dict__' of 'B' objects>, '__weakref__': <attribute '__weakref__' of 'B' objects>, '__init__': <function B.__init__ at 0x0000000000A62488>}
    {'_B__name': 'egon'}
    {'_B__name': 'egon', '__age': 18}
    18
    

    变形的过程只在类的定义是发生一次,在定义后的赋值操作,不会变形

     3、在继承中,父类如果不想让子类覆盖自己的方法,可以将方法定义为私有的

    1、代码

    class A:
        def foo(self):
            print('A.foo')
    
        def bar(self):
            print('A.bar')
            self.foo() #b.foo()
    
    class B(A):
        def foo(self):
            print('B.foo')
    
    b=B()
    b.bar()
    

    2、打印输出

    A.bar
    B.foo

    3、带注释的

    class A:
        def __foo(self): #在定义时就变形为_A__foo
            print('A.foo')
    
        def bar(self):
            print('A.bar')
            self.__foo() #只会与自己所在的类为准,即调用_A__foo
    
    class B(A):
        def __foo(self): #_B__foo
            print('B.foo')
  • 相关阅读:
    团队冲刺(九)
    团队冲刺(八)
    团队冲刺(七)
    团队冲刺(六)
    团队冲刺(五)
    背景图片-密度屏幕(移动端)
    响应字体大小(移动端)
    FLEX 布局
    图片垂直居中
    css reset
  • 原文地址:https://www.cnblogs.com/luoahong/p/9927702.html
Copyright © 2011-2022 走看看