zoukankan      html  css  js  c++  java
  • 面向对象之封装

    一:封装

    【1】基础概念

    (1)什么是封装:

      (1)字面意思是将什么封存在什么里面 达到隐藏的效果

       例如:将电脑里的硬件封装在机盒中 

      (2)在程序中是将复杂的 丑陋的的细节封装在内部 对外部提供简易的接口 供人们使用

        例如:电脑开机需要调度大量的硬件 但是这些硬件我们本身根本不需要考虑 直接使用开机键这个简单的接口就行

    (2)封装的好处:

      (1)保证数据的安全性:

      (2)对外部隔离内部细节 降低复杂度

    (3)封装使用场景:

      (1)一些数据不希望外界直接修改的时

        例如:数据库中的个人信息如果外部访问可以随时修改 会导致数据随时被篡改的危险

      (2)一些函数不希望给外部直接使用的时候

        例如:电脑开机的时候 加载操作系统 这些方式本身人为不需要管 因为只需要定义好 由硬件直接操作就可以 人为不需要干预

    (4)封装的使用方式:

      (1):对属性进行封装

    例如:

    class Person:
        def __init__(self,name,id_card):
            self.name = name
            self.__id_card = id_card
    
        def show_id_cart(self):
            return print(self.__id_card)
    
    
    p = Person('SR',123456789)
    
    print(p.id_card) # 123456789原始身份证信息
    
    p.id_card = 987654321
    
    print(p.id_card) # 987654321 身份证被修改
    
    # 对数据进行封装
    p.show_id_cart()  # 123456789原始函数
    对属性进行数据封装

    PS:上述通过对属性进行封装 提高数据的安全性

      (2)对方法进行封装

    例如:

    # class Person:
    #     def __init__(self,name,id_card):
    #         self.name = name
    #         self.__id_card = id_card
    #
    #     def show_id_cart(self):
    #         return print(self.__id_card)
    #
    #
    # p = Person('SR',123456789)
    #
    # print(p.id_card) # 123456789原始身份证信息
    #
    # p.id_card = 987654321
    #
    # print(p.id_card) # 987654321 身份证被修改
    #
    # # 对数据进行封装
    # p.show_id_cart()  # 123456789原始函数
    
    
    
    class PC:
        def __init__(self,kind,price,):
            self.kind = kind
            self.price = price
    
        def open(self):
                print("接通电源")
                self.__check_device()
                print("载入内核")
                self.__start_services()
                print("初始化内核")
                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....")
    
    
    p = PC('apple',18888)
    
    p.open() # 正常启动
    
    p.__login()  # 报错
    对方法进行数据封装

    PS:

    (1)对方法进行封装 防止不必要的方法被外界调用

    (2)将不必须要的方法封装 只需要给外部提供一个可以访问的接口即可 降低复杂度

    (5)封装特点:

      (1)内部可以访问内部被封装的函数或者属性

      (2)外部不可以直接访问内部被封装的函数或者属性

    【2】封装扩展:

    (1)权限问题

      (1)默认属于公有的 大家都可以使用

      (2)被封装之后即属于私有的 只能由当前类自己使用 外部不能直接调用

    (2)如何访问被封装的属性:

    (1)产生背景

      (1)如果内部属性与方法被进行封装 导致外部不能直接读取 那么这些属性存在也没有直接意义

        例如:上述用户不能直接读取直接的身份证,电脑使用开机键 也不能去取内部加载程序 

      (2)通过特殊的方法进行访问内部被封装属性或者方法

    例如:

    # # class Person:
    # #     def __init__(self,name,id_card):
    # #         self.name = name
    # #         self.__id_card = id_card
    # #
    # #     def show_id_cart(self):
    # #         return print(self.__id_card)
    # #
    # #
    # # p = Person('SR',123456789)
    # #
    # # print(p.id_card) # 123456789原始身份证信息
    # #
    # # p.id_card = 987654321
    # #
    # # print(p.id_card) # 987654321 身份证被修改
    # #
    # # # 对数据进行封装
    # # p.show_id_cart()  # 123456789原始函数
    #
    #
    #
    # class PC:
    #     def __init__(self,kind,price,):
    #         self.kind = kind
    #         self.price = price
    #
    #     def open(self):
    #             print("接通电源")
    #             self.__check_device()
    #             print("载入内核")
    #             self.__start_services()
    #             print("初始化内核")
    #             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....")
    #
    #
    # p = PC('apple',18888)
    #
    # p.open() # 正常启动
    #
    # p.__login()  # 报错
    
    
    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:
                # 定义下载数据 类内部可以访问内部封装属性
                self.__buffer_size = size
    
    
    # 只允许每次下载1M
    d = Downloader('新闻联播','百度',1024*1024)
    # d.start_download()
    
    # 自己私定义下载属性 因此需要对内部数据进行封装
    # d.buffer_size = 1024*1024*10
    # d.start_download()
    
    '''
    1:虽然现在通过封装导致内部属性不能被随便修改
    2:但是却将内部属性给限制死了 假如电脑配置比较差 每次只能读取0.5M的 
    3:现在却只能下载1m 
    '''
    # 外部调用新的函数
    d.set_buffer_size(1024*1024/2)
    d.start_download() #  524288.0 下载大小
    
    '''
    但是这样也没有意义  封装没有必要了 不如直接赋值为某个值
    但是现在这个属于函数 可以添加额外的逻辑 或者属性
    例如:加入用户上传字符串 现在不合理 我通过现在用户只能上传数字
    
    '''
    d.set_buffer_size('132132') # 丢雷楼某 顶你个肺啊 不知道输入数字啊
    
    d.set_buffer_size(1024*512)
    d.start_download() #  524288
    定义方法类对内部函数进行属性修改

    PS:内部通过创建新的函数 主要可以进行一些逻辑上的判断

    (3)装饰器

      (1)property:

        (1)在上述中因为被封装成私有属性 私有属性与公有属性调用方式不同

        (2)用户需要知道那个是私有 那个是公有的 为了统一调用方式 需要进行装饰

    例如:

    class User_info:
        def __init__(self,name,id_cart):
            self.name = name
            # 为了防止内部数据被外部随便修改 进行封装
            self.__id_cart = id_cart
    
        @property
        def id(self):
            return self.__id_cart
    
    user = User_info('SR',12345678)
    
    # 被装饰之前
    print(user.id()) # 12345678 被装饰之前
    
    # 装饰后
    print(user.id) # 12345678
    property属性

      (2)setter

        (1)可以将私有属性按照普通属性的形式 进行修

    例如:

    class User_info:
        def __init__(self,name,id_cart):
            self.name = name
            # 为了防止内部数据被外部随便修改 进行封装
            self.__id_cart = id_cart
    
        @property
        def id(self):
            return self.__id_cart
    
        @id.setter
        def id(self,new_id):
            # 添加条件限制
            if type(new_id) == int:
                self.__id_cart = new_id
                # 查看该函数是否被行
                print('代码正在执行') # 代码正在执行
                print(self.__id_cart) # 987654321
            else:
                print('丢雷楼某 顶你个肺啊 能不能好好输入啊!')
    
    
    user = User_info('SR',12345678)
    
    user.id = 987654321
    
    print(user.id) # 987654321
    
    user.id = 'SR'
    print(user.id) # 丢雷楼某 顶你个肺啊 能不能好好输入啊!
    setter属性

      (3)delete

    class User_info:
        def __init__(self,name,id_cart):
            self.name = name
            # 为了防止内部数据被外部随便修改 进行封装
            self.__id_cart = id_cart
    
        @property
        def id(self):
            return self.__id_cart
    
        @id.setter
        def id(self,new_id):
            # 添加条件限制
            if type(new_id) == int:
                self.__id_cart = new_id
                # 查看该函数是否被行
                print('代码正在执行') # 代码正在执行
                print(self.__id_cart) # 987654321
            else:
                print('丢雷楼某 顶你个肺啊 能不能好好输入啊!')
        @id.deleter
        def id(self):
            print('删除属性')
    
            # 删除属性
            del self.__id_cart
    
    user = User_info('SR',12345678)
    
    del user.id
    #此时代码并没有被真正删除
    print(user.id) # 删除属性
    delete 属性

    (4)封装的实现原理:

      (1)就是在加载类的时候将__替换成了 _类名__

    例如:

    class Number:
        def __init__(self,number):
            self.__number = number
    
        @property
        def number(self):
            return self.__number
    
    
    n = Number(123)
    
    print(n.__dict__) # {'_Number__number': 123}
    
    print(n._Number__number) # 123

    (5)计算属性:

      (1)属性的值 不能直接获取 必须通过计算获取

    例如:

    class Spure:
        def __init__(self,len):
            self.len = len
    
        @property
        def area(self):
            return self.len*self.len
    
    
    s = Spure(10)
    s.len = 20
    print(s.area) # 400
    
    s.len = 4
    print(s.area)  # 16

    (6)接口:

      (1)接口是一组功能的集合 但是接口只包含功能的名字 不包含功能代码

      (2)其实本质就是一套标准协议 遵循这个标准协议的代码 就能被调用

      (3)如果子类没有按照规范进行编写 也不能阻止代码运行

    (2)抽象类

      (1)没有具体功能(函数体代码)的类

      (2)限制子类中必须定义的方法

    (3)鸭子类型

      (1)python具体不会限制人们该怎么写代码

      (2)如果这个对象长的像鸭子 走路像鸭子就是鸭子类型

      (3)即你只要按照相关协议来编写代码 也可以达到提高扩展性的目的

  • 相关阅读:
    bzoj 4361: isn
    bzoj 2560: 串珠子
    bzoj 3622: 已经没有什么好害怕的了
    UOJ #30. 【CF Round #278】Tourists
    Codeforces Round #452 E. New Year and Old Subsequence
    bzoj 2653: middle
    codeforces701C
    codeforces437C
    codeforces518B
    codeforces706C
  • 原文地址:https://www.cnblogs.com/SR-Program/p/11252818.html
Copyright © 2011-2022 走看看