zoukankan      html  css  js  c++  java
  • 封装

    封装

    1、封装的目的?

    隐藏对象属性和实现细节,仅对外提供公共访问方式

    2.【好处】

    1. 将变化隔离;

    2. 便于使用;

    3. 提高复用性;

    4. 提高安全性;

    3.【封装原则】

    ​ 1. 将不需要对外提供的内容都隐藏起来;

    ​ 2. 把属性都隐藏,提供公共方法对其访问。

    4.封装方法:

    class PC:
        def __init__(self,price,kind,color):
            self.price = price
            self.kind = kind
            self.color = color
    
        def open(self):
            print("接通电源")
            self.__check_device()
            print("载入内核")
            print("初始化内核")
            self.__start_services()
            print("启动GUI")
            self.__login()
    
    
        def __check_device(self):
            print("硬件检测1")
            print("硬件检测2")
            print("硬件检测3")
            print("硬件检测4")
    
        def __start_services(self):
            print("启动服务1")
            print("启动服务2")
            print("启动服务3")
            print("启动服务4")
    
        def  __login(self):
            print("login....")
            print("login....")
            print("login....")
    
    pc1 = PC(20000,"香蕉","黄色")
    pc1.open()
    
    

    5.私有变量和私有方法

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

    其实这仅仅这是一种变形操作
    类中所有双下划线开头的名称如___x都会自动变形成:类名__x的形式:__id_numbe_Person__id_number

    class Person:
        def __init__(self, id_number, name, age):
            self.__id_number = id_number#语法上可以将类的数据属性设置成私有如,__id_number,会变形为_Person__id_number
            self.name = name
            self.age = age
            
        def show_id(self):
            print(self.__id_number)#只有类的内部才可以通过__id_number的方法访问到
    
    p = Person("1111111111111", "jack", 29)
    
    p.__id_number = "222"
    print(p.__id_number)
    
    p.show_id()
    

    这种自动变形的特点:

    1.类中定义的__x只能在内部使用,如self.__id_number,引用的就是变形的结果。

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

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

    这种变形需要注意的问题是(1访问2修改3变形范围):

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

    p = Person("1111111111111", "jack", 29)
    print(p.__id_number)#外部不能直接访问
    #AttributeError: 'Person' object has no attribute '__id_number'
    print(p._Person__id_number)#拼出隐藏的后的名字,竟然就可以在访问了
    #1111111111111
    

    2、通过内部函数修改可以修改内部封装的属性

    2.变形的过程只在类的内部生效,在定义后的赋值操作,不会变形

    p = Person("1111111111111", "jack", 29)
    
    p.__id_number = "222"
    print(p.__id_number)
    #结果为222
    

    在外界访问私有的内容

    原理:通过内部函数修改可以修改内部封装的属性

    """
    这是一个下载器类,需要提供一个缓存大小这样的属性
    缓存大小不能超过内存限制
    
    """
    class Downloader:
        def __init__(self,filename,url,buffer_size):
            self.filename = filename
            self.url = url
            self.__buffer_size= buffer_size#将缓冲区设置成私有的
    
        def start_download(self):#开始下载函数
            if self.__buffer_size <= 1024*1024:
                print("开始下载....")
                print("当前缓冲器大小",self.__buffer_size)
            else:
                print("内存炸了! ")
    
    
        def set_buffer_size(self,size):#设置缓冲区大小
            if not type(size) == int:#进行一个小的逻辑判断
                print("大哥 缓冲区大小必须是整型")
            else:
                print("缓冲区大小修改成功!")
                self.__buffer_size = size#通过内部函数修改可以修改内部封装的属性
    
        def get_buffer_size(self):#返回缓冲区大小
            return self.__buffer_size
    
    d = Downloader("葫芦娃","http://www.baicu.com",1024*1024)
    #实现步骤:
    # 1、通过函数修改内部封装的属性
    d.set_buffer_size(1024*512)
    
    # 2、通过函数访问内部封装的属性
    print(d.get_buffer_size())
    print(d.filename)
    
    d.start_download()
    
    
    

    这样一来我们可以在外界修改这个关键数据时,做一些限制

    property装饰器

    通过方法来修改或访问属性,本身没什么问题,但是这给对象的使用者带来了麻烦.

    使用必须知道哪些是普通属性,哪些是私有属性,需要使用不同的方式来调用他们

    property装饰就是为了使得调用方式一致

    使用property装饰器可以将一个方法伪装成普通顺属性,保持属性之间调用方法一致

    有三个相关的装饰器

    1.property   该装器用在获取属性的方法上 
    2.@key.setter  该装器用在修改属性的方法上 
    3.@key.deleter 该装器用在删除属性的方法上 
    
    
    注意:key是被property装饰的方法的名称 也就是属性的名称 
    内部会创建一个对象 变量名称就是函数名称  
    所以在使用setter和deleter时 必须保证使用对象的名称取调用方法 
    所以是 key.setter
    
    class A:
        def __init__(self,name,key):
            self.__name = name
            self.__key = key
    
        @property#
        def key(self):
            return self.__key
    
        @key.setter
        def key(self,new_key):
            if new_key <= 100:
                self.__key = new_key
            else:
                print("key 必须小于等于100")
    
        @key.deleter
        def key(self):
            print("不允许删除该属性")
            del self.__key
            
    
    

    加入装饰器后的语法

    a = A("jack",123)
    print(a.key)#访问被隐藏的属性。和正常访问一样
    或者:
    print(a._A__key)
    a.key = 321#在加入@.setter语法后,可以直接访问到隐藏的key,可以直接赋值,修改值
    print(a.key)
    

    python实现封装的原理

    就是在加载类的时候,把__替换成了 _类名__

    封装:

    对外部隐藏内部的实现细节,并提供访问的接口

    好处:

    ​ 1.提高安全性

    ​ 2.隔离复杂度

    语法:将要封装的属性或方法名称前加上双下划线

    访问被隐藏的属性:

    ​ 提供用于访问和修改的方法

    访问:用隐藏起来的名字

    修改:用类内部的函数

    使用property装饰器可以将一个方法伪装成普通顺属性,报纸属性之间调用方法一致

    封装的实现原理 ,替换变量名称

    property 可以用来实现计算属性

    计算属性指的是:属性的值,不能直接获得,必须通过计算才能获取

    例如:正方形求面积

    class Square:
        def __init__(self,width):
            self.width=width
        @property
        def area(self):
            return self.width**2
    s = Square(10)
    # print(s.area())#100,当出现@property,则为属性,不可加括号!
    s.width=20
    # print(s.area())#400,当出现@property,则为属性,不可加括号!
    s.width=2
    print(s.area)#当出现@property,则为属性,不可加括号!
    4
    

    接口

    接口是一组功能的集合,但是接口中仅包含功能的名字,不包含具体的实现代码

    接口本质是一套协议标准,遵循这个标准的对象就能被调用

    接口目的就是为了提高扩展性:

    例如电脑提前指定制定一套USB接口协议,只要你遵循该协议,你的设备就可以被电脑使用,不需要关心到底是鼠标还是键盘

    class USB:
        def open(self):
            pass
    
        def close(self):
            pass
    
        def  read(self):
            pass
    
        def write(self):
            pass
    
    class Mouse(USB):
        def open(self):
            print("鼠标开机.....")
    
        def close(self):
            print("鼠标关机了...")
    
        def read(self):
            print("获取了光标位置....")
    
        def write(self):
            print("鼠标不支持写入....")
    
    def pc(usb_device):
        usb_device.open()
        usb_device.read()
        usb_device.write()
        usb_device.close()
    
    m = Mouse()
    # 将鼠标传给电脑
    pc(m)
    
    class KeyBoard(USB):
        def open(self):
            print("键盘开机.....")
    
        def close(self):
            print("键盘关机了...")
    
        def read(self):
            print("获取了按键字符....")
    
        def write(self):
            print("可以写入灯光颜色....")
    
    # 来了一个键盘对象
    k = KeyBoard()
    pc(k)
    

    抽象类

    abc 不是随意取的 而是单词的缩写
    abstract class
    翻译为抽象类
    抽象类的定义 :
    类中包含 没有函数体的方法

  • 相关阅读:
    使用HSQLDB 客户端(jvm自带数据库使用技巧)
    PageHelper分页
    使用exe4j打包Java程序
    有图形界面的聊天程序
    同时收发消息
    服务端和客户端互聊
    使用Scanner
    收发字符串
    收发数字
    建立连接
  • 原文地址:https://www.cnblogs.com/ZDQ1/p/11253162.html
Copyright © 2011-2022 走看看