面向对象:论封装的重要性

面向对象的基本概念包括对象、类、抽象、封装、继承、多态、接口、消息、组件、复用和模式等。

封装

  访问权限的控制常被称为是具体实现的隐藏。把数据和方法包装进类中,以及具体实现的隐藏共同被称为封装

public protected default private
同类
同包
子类
通用性

public:可以被所有其他类访问

protected:自身、子类、及同一个包中类(接受包外的子类访问)

default:同一包中的类可以访问,声明时没有加修饰符,认为是friendly(拒绝一切外包访问)

private:只能被自己访问和修改

  类的访问控制符只有三种:public、private、protected

  default是无访问控制符

封装:将相关的概念组成一个单元模块,并通过一个名称来引用它。面向对象封装是将数据和基于数据的操作封装成一个整体对象,对数据的访问或修改只能通过对象对外提供的接口进行。

面向对象特点

1、是一种符合人们思考习惯的思想。
2、将复杂的问题简单化。
3、使程序员从动作的执行者变为动作的指挥者。
4、完成指定的需求时:

      先去找具有所需功能的对象来用。
      如果该对象不存在,那么创建一个具有所需功能的对象。
      这样简化了开发并且提高了复用性。
     面向对象开发、设计、过程

开发过程:其实就是不断的创建对象、调用对象、指挥对象做事情。

设计过程:其实就是在管理和维护对象与对象之间的关系。

一. 封装不是单纯意义的隐藏

封装的真谛在于明确地区分内外,封装的属性可以直接在内部使用,而不能被外部直接使用,然而定义属性的目的终归是要用,外部要想用类隐藏的属性,需要我们为其开辟接口,让外部能够间接地用到我们隐藏起来的属性,那这么做的意义何在???

1:封装数据:将数据隐藏起来这不是目的。隐藏起来然后对外提供操作该数据的接口,然后我们可以在接口附加上对该数据操作的限制,以此完成对数据属性操作的严格控制。

View Code

2:封装方法:目的是隔离复杂度

封装方法举例: 

1\. 你的身体没有一处不体现着封装的概念:你的身体把膀胱尿道等等这些尿的功能隐藏了起来,然后为你提供一个尿的接口就可以了(接口就是你的。。。,),你总不能把膀胱挂在身体外面,上厕所的时候就跟别人炫耀:hi,man,你瞅我的膀胱,看看我是怎么尿的。

2\. 电视机本身是一个黑盒子,隐藏了所有细节,但是一定会对外提供了一堆按钮,这些按钮也正是接口的概念,所以说,封装并不是单纯意义的隐藏!!!

3. 快门就是傻瓜相机为傻瓜们提供的方法,该方法将内部复杂的照相功能都隐藏起来了

提示:在编程语言里,对外提供的接口(接口可理解为了一个入口),可以是函数,称为接口函数,这与接口的概念还不一样,接口代表一组接口函数的集合体。

隔离复杂度的例子

 

3: 了解

python并不会真的阻止你访问私有的属性,模块也遵循这种约定,如果模块名以单下划线开头,那么from module import 时不能被导入,但是你from module import _private_module依然是可以导入的*

其实很多时候你去调用一个模块的功能时会遇到单下划线开头的(socket._socket,sys._home,sys._clear_type_cache),这些都是私有的,原则上是供内部调用的,作为外部的你,一意孤行也是可以用的,只不过显得稍微傻逼一点点

python要想与其他编程语言一样,严格控制属性的访问权限,只能借助内置方法如__getattr__,详见面向对象进阶

四 特性(property) 

什么是特性property

property是一种特殊的属性,访问它时会执行一段功能(函数)然后返回值

例一:BMI指数(bmi是计算而来的,但很明显它听起来像是一个属性而非方法,如果我们将其做成一个属性,更便于理解)

成人的BMI数值:

过轻:低于18.5

正常:18.5-23.9

过重:24-27

肥胖:28-32

非常肥胖, 高于32

  体质指数(BMI)=体重(kg)÷身高^2(m)

  EX:70kg÷(1.75×1.75)=22.86

例二:圆的周长和面积 

#注意:此时的特性arear和perimeter不能被赋值
c.area=3 #为特性area赋值
''' 抛出异常:
AttributeError: can't set attribute '''

为什么要用property

将一个类的函数定义成特性以后,对象再去使用的时候obj.name,根本无法察觉自己的name是执行了一个函数然后计算出来的,这种特性的使用方式遵循了统一访问的原则

除此之外,看下

ps:面向对象的封装有三种方式:
【public】
这种其实就是不封装,是对外公开的
【protected】
这种封装方式对外不公开,但对朋友(friend)或者子类(形象的说法是“儿子”,但我不知道为什么大家 不说“女儿”,就像“parent”本来是“父母”的意思,但中文都是叫“父类”)公开
【private】
这种封装对谁都不公开

python并没有在语法上把它们三个内建到自己的class机制中,在C++里一般会将所有的所有的数据都设置为私有的,然后提供set和get方法(接口)去设置和获取,在python中通过property方法可以实现

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'

 了解:一种property的古老用法

五 封装与扩展性

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

你可能感兴趣的