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..')
  • 相关阅读:
    .net注册iis
    hdu 1081To The Max
    hdu 1312Red and Black
    hdu 1016Prime Ring Problem
    hdu 1159Common Subsequence
    hdu 1372Knight Moves
    hdu 1686Oulipo
    hdu 1241Oil Deposits
    hdu 1171Big Event in HDU
    hdu 4006The kth great number
  • 原文地址:https://www.cnblogs.com/sweet-i/p/11252771.html
Copyright © 2011-2022 走看看