• day23-类的封装


    1、封装

    封装,顾名思义就是将内容封装到某个地方,以后再去调用被封装在某处的内容。
    所以,在使用面向对象的封装特性时,需要:
    1)将内容封装到某处
    2)从某处调用被封装的内容

    第一步:将内容封装到某处

    class Foo:
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
    #根据Foo类构造obj1对象,自动执行Foo类的__init__方法
    #将Tom和20分别封装到self也就是obj1的name和age属性中
    obj1 = Foo('Tom',20)
    
    #根据Foo类构造obj2对象,自动执行Foo类的__init__方法
    #将Mike和25分别封装到self也就是obj2的name和age属性中
    obj2 = Foo('Mike',25)

    self 是一个形式参数,当执行 obj1 = Foo('Tom', 20)时,self等于obj1
    当执行 obj2 = Foo('Mike', 25)时,self等于obj2

    所以,内容其实被封装到了对象obj1和obj2中,每个对象中都有name和age属性,在内存里类似于下图来保存。

    第二步:从某处调用被封装的内容

    调用被封装的内容时,有两种情况:
    1)通过对象直接调用
    2)通过self间接调用

    1、通过对象直接调用被封装的内容
    上图展示了对象 obj1 和 obj2 在内存中保存的方式,根据保存格式可以如此调用被封装的内容:对象.属性名

    class Foo:
        def __init__(self, name, age):
            self.name = name
            self.age = age
     
    obj1 = Foo('Tom', 20)
    print(obj1.name)    # 直接调用obj1对象的name属性
    print(obj1.age)     # 直接调用obj1对象的age属性
     
    obj2 = Foo('Mike', 25)
    print(obj2.name)    # 直接调用obj2对象的name属性
    print(obj2.age)     # 直接调用obj2对象的age属性

    2、通过self间接调用被封装的内容
    执行类中的方法时,需要通过self间接调用被封装的内容

    class Foo:
        def __init__(self, name, age):
            self.name = name
            self.age = age
      
        def detail(self):
            print(self.name)
            print(self.age)
      
    obj1 = Foo('Tom', 20)
    obj1.detail()  # Python默认会将obj1传给self参数,即:obj1.detail(obj1),所以,此时方法内部的self = obj1,即:self.name是Tom,self.age是20
      
    obj2 = Foo('Mike', 25
    obj2.detail()  # Python默认会将obj2传给self参数,即:obj1.detail(obj2),所以,此时方法内部的self = obj2,即:self.name是Mike, self.age是25

    综上所述,对于面向对象的封装来说,其实就是使用构造方法将内容封装到对象中,然后通过对象直接或者self间接获取被封装的内容。

    2、封装与扩展性

    封装在于明确区分内外,使得类实现者可以修改封装内的东西而不影响外部调用者的代码;而外部使用用者只知道一个接口(函数),只要接口(函数)名、参数不变,使用者的代码永远无需改变。这就提供一个良好的合作基础——或者说,只要接口这个基础约定不变,则代码改变不足为虑。

    #类的设计者
    class Room:
        def __init__(self,name,owner,width,length,high):
            self.name=name
            self.owner=owner
            self.__width=width
            self.__length=length
            self.__high=high
        def tell_area(self): #对外提供的接口,隐藏了内部的实现细节,此时我们想求的是面积
            return self.__width * self.__length
    
    #使用者
    >>> r1=Room('卧室','egon',20,20,20)
    >>> r1.tell_area() #使用者调用接口tell_area
    
    #类的设计者,轻松的扩展了功能,而类的使用者完全不需要改变自己的代码
    class Room:
        def __init__(self,name,owner,width,length,high):
            self.name=name
            self.owner=owner
            self.__width=width
            self.__length=length
            self.__high=high
        def tell_area(self): #对外提供的接口,隐藏内部实现,此时我们想求的是体积,内部逻辑变了,只需求修该下列一行就可以很简答的实现,而且外部调用感知不到,仍然使用该方法,但是功能已经变了
            return self.__width * self.__length * self.__high
    
    
    #对于仍然在使用tell_area接口的人来说,根本无需改动自己的代码,就可以用上新功能
    >>> r1.tell_area()

    例子1:

    class Parent:
        def func(self):
            print('in Parent func')
    
        def __init__(self):
            self.func()
    
    class Son(Parent):
        def func(self):
            print('in Son func')
    
    son1 = Son()
    结果是打印了in Son func

    在实例化Son类时的流程:
    1、在内存中创建了一个空间存储实例化对象son1
    2、将实例化对象son1的内存指针指向Son类
    3、自动执行Son类中的__init__方法,并将实例化对象son1传给self
    4、由于Son类中没有__init__方法,所以就从父类Parent中寻找__init__方法并执行
    5、执行父类中的__init__方法,调用了self.func()函数,而此时self是实例化对象son1,所以执行的是son1的func方法
    6、son1的func方法打印in Son func

    例子2:

    class A:
        a = 0
        b = 1
        def __init__(self):
            c = 222
    d = A()
    d.a = 1
    d.b = 2
    d.c = {'1':1}
    e = A()
    print(e.a)
    print(e.b)
    print(e.c)
    结果:0 1 报错'A' object has no attribute 'c'

    1、创建A类时,在A类中定义了静态属性a和b,创建了特殊方法__init__,c=222并不是创建了静态属性,也没有返回c,所以c在内存中并不存在
    2、实例化对象d=A(),在d的空间内创建了静态属性a,b,c,但并不会修改A类中的属性
    3、实例化对象e=A(),e可以调用A类中的静态属性a和b,但是A类中并不存在静态属性c,所以e.c会报错

  • 相关阅读:
    Android 平板模拟器内存修改
    UI设计另类,创意的网站和App 集合(持续更新)
    Android平台根据分辨率计算屏幕尺寸,基于物理尺寸来验证手机和平板应用合并的可行性
    shape和selector的结合使用
    RGB浅谈
    Android开发大牛们的博客地址(持续更新)
    解决ViewPager添加点击监听器无触发的问题
    VC 输出闪烁的字母
    计算机体系结构精要
    Xmanager远程连接Ubuntu,窗口无法输入字母'd'
  • 原文地址:https://www.cnblogs.com/dxnui119/p/9973787.html
Copyright © 2020-2023  润新知