《编程导论(Java)·6.1封装性》-什么是封装


1.通常的解释

你可以不看这一部分的东西。下面摘录的是一些通常的说法:百度百科面向对象技术

【面向对象技术的基本特征主要有抽象性、封装性、继承性和多态性。

封装(Encapsulation)就是把对象的属性和行为结合成一个独立的单位,并尽可能隐蔽对象的内部细节。封装有两个含义:一是把对象的全部属性和行为结合在一起,形成一个不可分割的独立单位。对象的属性值(除了公有的属性值)只能由这个对象的行为来读取和修改;二是尽可能隐蔽对象的内部细节,对外形成一道屏障,与外部的联系只能通过外部接口实现。
封装是通过限制只有特定类的对象可以访问这一特定类的成员,而它们通常利用接口实现消息的传入传出。举个例子,接口能确保幼犬这一特征只能被赋予狗这一类。通常来说,成员会依它们的访问权限被分为3种:公有成员、私有成员以及保护成员。有些语言更进一步:Java可以限制同一包内不同类的访问;C#和VB.NET保留了为类的成员聚集准备的关键字:internal(C#)和Friend(VB.NET);Eiffel语言则可以让用户指定哪个类可以访问所有成员。 
封装的信息隐蔽作用反映了事物的相对独立性,可以只关心它对外所提供的接口,即能做什么,而不注意其内部细节,即怎么提供这些服务。例如,用陶瓷封装起来的一块集成电路芯片,其内部电路是不可见的,而且使用者也不关心它的内部结构,只关心芯片引脚的个数、引脚的电气参数及引脚提供的功能,利用这些引脚,使用者将各种不同的芯片连接起来,就能组装成具有一定功能的模块。
封装的结果使对象以外的部分不能随意存取对象的内部属性,从而有效地避免了外部错误对它的影响,大大减小了查错和排错的难度。另一方面,当对象内部进行修改时,由于它只通过少量的外部接口对外提供服务,因此同样减小了内部的修改对外部的影响。同时,如果一味地强调封装,则对象的任何属性都不允许外部直接存取,要增加许多没有其他意义,只负责读或写的行为。这为编程工作增加了负担,增加了运行开销,并且使得程序显得臃肿。为了避免这一点,在语言的具体实现过程中应使对象有不同程度的可见性,进而与客观世界的具体情况相符合。
封装机制将对象的使用者与设计者分开,使用者不必知道对象行为实现的细节,只需要用设计者提供的外部接口让对象去做。封装的结果实际上隐蔽了复杂性,并提供了代码重用性,从而降低了软件开发的难度。

(Stanley B.Lippman / Josee Lajoie / Barbara E.Moo .C++ Primer:人民邮电出版社,2010)】


2.学习思路

《编程导论(Java)·6.1封装性》,按照如下思路介绍封装性: Parnas原则-类的接口-封装
(1)封装(Encapsulation)是指将对象的全部属性和方法包裹起来,形成一个不可分割的整体。在OO中,封装的一句话解释,关键词是“整体”或数据抽象。
“整体”,用细胞膜来形容封装是很好的。


关于“整体”似乎没有太多好说的东西。类,你 总得让它成为一个软件实体,当然要搞成一个“整体”。用一对大括号将类的成员和非成员包裹起来,仅保留外界能够访问的接口。 包裹动作和形成接口是一个硬币的两面。包裹动作是程序工人的不太繁重的体力劳动——实际上对于方法也有同样的包装动作——用一对大括号将各种语句包裹成一个整体。

(2)封装这个概念,在C语言中,用于函数的封装,因而有Parnas原则——接口与实现分离;在面向对象技术中,则用于形成类的接口,因而是Parnas原则的推广。
需要注意的是:
在早期,人们将方法层面的接口与实现相分离称为信息隐藏。例如在全世界程序员奉为经典的《人月神话(二十周年纪念版)》中,Brooks以《关于信息隐藏,Parnas 是正确的,我是错误的》作为纪念版一节的标题。Brooks的此举令人敬仰。
本书中,
信息隐藏,指外界是否能够访问;而接口与实现的分离,指程序员是否愿意了解方法的实现
换言之,形成类的接口即信息隐藏属于可见性议题;而程序员通常对( 不被隐藏的)接口的实现视而不见。

3.变化与封装

正如前言中提到的,“面向对象的封装、继承、动态绑定(方法改写)、多态等知识,在编程语言教学中并没有太多的理论含义(编程语言课程不涉及编程语言设计和形式化的内容)”,yqj2065比较轻视这几个概念。所以,封装写的很少。

《Think in java·第 5 章隐藏实施过程》的第一句话【将发生变化的东西与保持不变的东西分隔开】,理论上,对于“变化”,与封装一毛钱的关系都没有。
要点是,何谓变化?
  • 如果你的“变化”,是指信息隐藏部分的代码的自由修改,那么能够说封装了“变化”,这是Parnas原则(接口与实现分离)的必然后果。对于数据抽象或类A,用户只能够与其接口交互。只要A保证其接口不变,其内部实现就可以自由地演化。是的,这种自由源于封装,破坏这种自由就破坏了A的封装性。
  • 对于(需求)变化的封装,又称开放封闭原则OCP。这里的变化,指原来需求要求处理猫和狗,后来需求要求处理牛、马等。为了封装这种“变化”,我们的代码中将要处理的,是“动物”类型。(另一方面,OCP所言的对修改封闭,也不干涉被隐藏的实现可以自由演化)。
  • 类的接口能否修改?关于库(例如其中有类A)的设计,依赖库的程序B要求库是向下兼容的。这里,程序B依赖的是A的接口。不论库的创建者想怎样自由地进行修改与改进A,前提是不得修改A的接口。否则库不是兼容的。A的设计者不可能、也不会“考虑”该服务(的方法名、参数)未来是否保持不变或改变。如果你使用过一些修改过接口的第三方库,你肯定感受颇深。

  • 以JDK中的类为例,类的接口变化时采用的方式:
    列举 不赞成使用(Deprecated)的类的接口/方法
    Java8 的默认方法为Java接口的变化 提供后悔药。
最后,“封装变化”Find what varies and encapsulate it. 是面向对象设计/设计模式的中心思想,但是与封装性是两个概念。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值