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

    面向对象封装:

     封装就是隐藏对象的属性和实现细节,仅对外提供公共访问方式。

    封装的真谛在于明确地区分内外,封装的属性可以直接在内部使用,而不能被外部直接使用,

    然而定义属性的目的终归是要用,外部要想用类隐藏的属性,需要我们为其开辟接口,

    让外部能够间接地用到我们隐藏起来的属性;被封装的内容的特点:1.外界不能直接访问,2.内部依然可以使用。

    两个目的:

    ​   1.为了保证 关键数据的安全性。

      ​ 2.对外部隐藏实现细节,隔离复杂度。

    封装原则:

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

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

    学习了封装后就可以控制属性的权限;在python只要两种权限,

      1.公开的.默认就是公开的。

      2.私有的,只能由当前类自己使用。

    在外界访问私有的内容:

    属性虽然被封装了,但是还是需要使用的,在外界如何访问。

    通过定义方法类完成对私有属性的修改和访问。

    什么时候应该封装:

    ​ 当有一些数据不希望外界可以直接修改时

    ​ 当有一些函数不希望给外界使用时

    如何使用封装呢?语法如下:

    """ 
    在python中用双下划线开头的方式将属性隐藏起来(设置成私有的)
    其实这仅仅这是一种变形操作且仅仅只在类定义阶段发生变形
    类中所有双下划线开头的名称如__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是可以访问到的,
    #这种,在外部是无法通过__x这个名字访问到。

    封装方法:

    其目的是隔离复杂度。

    """
    在编程语言里,对外提供的接口(接口可理解为了一个入口),
    可以是函数,称为接口函数,这与接口的概念还不一样,接口代表一组接口函数的集合体。
    """ # 取款是功能,而这个功能有很多功能组成:插卡、密码认证、输入金额、打印账单、取钱 # 对使用者来说,只需要知道取款这个功能即可,其余功能我们都可以隐藏起来,很明显这么做 # 隔离了复杂度,同时也提升了安全性 class ATM: def __card(self): print('插卡') def __auth(self): print('用户认证') def __input(self): print('输入取款金额') def __print_bill(self): print('打印账单') def __take_money(self): print('取款') def withdraw(self): self.__card() self.__auth() self.__input() self.__print_bill() self.__take_money() a=ATM() a.withdraw()

    封装数据:

    """
    将数据隐藏起来这不是目的。隐藏起来然后对外提供操作该数据的接口,
    然后我们可以在接口附加上对该数据操作的限制,以此完成对数据属性操作的严格控制。
    """ class Teacher: def __init__(self,name,age): # self.__name=name # self.__age=age self.set_info(name,age) def tell_info(self): print('姓名:%s,年龄:%s' %(self.__name,self.__age)) def set_info(self,name,age): if not isinstance(name,str): raise TypeError('姓名必须是字符串类型') if not isinstance(age,int): raise TypeError('年龄必须是整型') self.__name=name self.__age=age t=Teacher('jack',18) t.tell_info() t.set_info('jack',19) t.tell_info()

    property装饰器:

    property就是将一个类的函数定义成特性以后,对象再去使用的时候obj.name,

    根本无法察觉自己的name是执行了一个函数然后计算出来的,这种特性的使用方式遵循了统一访问的原则。

    """
    property装饰就是为了使得调用方式一致;有三个相关的装饰器 :
    1.property   该装器用在获取属性的方法上 
    2.@key.setter  该装器用在修改属性的方法上 
    3.@key.deleter 该装器用在删除属性的方法上 
    key是被property装饰的方法的名称 也就是属性的名称 
    内部会创建一个对象 变量名称就是函数名称  
    所以在使用setter和deleter时 必须保证使用对象的名称取调用方法 
    所以是 key.setter
    """
    
    
    class Foo:
        def __init__(self,val):
            self.__NAME=val #将所有的数据属性都隐藏起来
    
        @property
        def name(self):
            return self.__NAME #obj.name访问的是self.__NAME(这也是真实值的存放位置)
    
        @name.setter
        def name(self,value):
            if not isinstance(value,str):  #在设定值之前进行类型检查
                raise TypeError('%s must be str' %value)
            self.__NAME=value #通过类型检查后,将值value存放到真实的位置self.__NAME
    
        @name.deleter
        def name(self):
            raise TypeError('Can not delete')
    
    f=Foo('egon')
    print(f.name)
    # f.name=10 #抛出异常'TypeError: 10 must be str'
    del f.name #抛出异常'TypeError: Can not delete'

    封装在于明确区分内外,使得类实现者可以修改封装内的东西而不影响外部调用者的代码;

    而外部使用用者只知道一个接口(函数),只要接口(函数)名、参数不变,使用者的代码永远无需改变。

    这就提供一个良好的合作基础——或者说,只要接口这个基础约定不变,则代码改变不足为虑。

    abc模块的使用:

    抽象类概念

    抽象类是一个特殊的类,只能被继承,不能实例化

    2.为什么要有抽象类

    其实在未接触抽象类概念时,我们可以构造香蕉、苹果、梨之类的类,然后让它们继承水果这个的基类,水果的基类包含一个eat函数。

    但是你有没有想过,我们可以将香蕉、苹果、梨实例化,去吃香蕉、苹果、梨。但是我们却不能将水果实例化,因为我们无法吃到叫水果的这个东西。

    所以抽象类中只能有抽象方法(没有实现功能),该类不能被实例化,只能被继承,且子类必须实现抽象方法。

    3.抽象类的作用

    在不同的模块中通过抽象基类来调用,可以用最精简的方式展示出代码之间的逻辑关系,让模块之间的依赖清晰简单。

    抽象类的编程,让每个人可以关注当前抽象类的方法和描述,而不需要考虑过多的实现细节,这对协同开发有很大意义,也让代码可读性更高。

    """
    abc 不是随意取的 而是单词的缩写
    abstract class
    翻译为抽象类
    抽象类的定义 :
    类中包含 没有函数体的方法
    
    """
    
    import abc
    
    class AClass(metaclass=abc.ABCMeta):
    
        @abc.abstractmethod
        def run(self):
            pass
        @abc.abstractmethod
        def run1(self):
            pass
    
    
    class B(AClass):
    
        def run(self):
            print("runrunrurn...")
    
    b = B()

    接口:

    接口是一套协议规范,明确子类们应该具备哪些功能;抽象类是用于强制要求子类必须按照协议中规定的来实现;

    然而,python不推崇限制你的语法, 我们可以设计成鸭子类型,既让多个不同类对象具备相同的属性和方法;

    对于使用者而言,就可以以不变应万变,轻松的使用各种对象;只要遵循了USB接口协议,都能够被电脑所调用;

    接口主要是方便了对象的使用者,降低使用者的学习难度;只要学习一套使用方法,就可以以不变应万变。

    class Interface:
         
        def f1(self):
            '''
            to do something
            :return:
            '''
     
    class Something(Interface):
         
        def f1(self):
            print('to do something...')
         
        def f2(self):
            print('to do other..')
  • 相关阅读:
    图书馆业务制图
    单元测试(输入一个数组和它的大小,输出这个数组中最大子数组的和)
    build to win读后感
    小学四则运算
    微信公众平台具体方案和人员分工
    问卷调查结果剖析
    题目确定与需求分析
    课程介绍与团队简介
    网站LOGO以及网页样式
    C Sharp进行网站信息抽取与小型内部搜索引擎的讲解
  • 原文地址:https://www.cnblogs.com/sweet-i/p/11252771.html
Copyright © 2011-2022 走看看