“你好,阿米戈!今天的课我想专门讲讲封装它的概况你可能已经有所了解。”

封装 - 1

封装有哪些优势呢?封装的优势有很多,但我想主要介绍下个人认为最重要的 4 个优势:

1) 验证内部状态。

程序里经常有好几个类和同一个对象交互。当多个类同时与一个对象的内部数据交互时,就有可能会破坏该对象的数据完整性,导致对象无法正常运行。

所以,对象必须追踪其内部数据的所有变更,或者最好由对象本身去变更。

如果我们不希望某些类变量被其他类更改,那我们就需要声明它为 private,那表示只有这个类的方法才可以访问它。如果我们想让有些变量对其他类只读,那我们可以给这些变量加上 public getter

例如,我们可能想让大家都知道我们的集合中有多少个元素,但是没有我们的允许任何人都不可以更改。这时,我们可以声明某个变量为 private int count,同时声明一个方法为 public getCount()

妥当的封装可以确保其他类无法直接访问我们类的内部数据,因此,不经过我们的管控,它们也无法进行修改。要想修改类上的变量,它们就必须调用类上的方法。

要知道,其他程序员在使用你的类的时候,总是选择对他们而言最简便的方法,而不是对你(或你的类)而言最安全的方法。封装就是给他们留错误、设障碍的一个好办法。

2) 参数检查。

有时,你需要检查传递进类的方法的参数。假定我们有一个名为“person”的类,你可以指定出生日期。我们要检查传递的数据是否符合程序的逻辑以及类的逻辑。例如,一年里没有 13 月,2 月没有 30 号等等。

“那为什么有人的出身日期是 2 月 30 号呢?”

“首先,有可能是因为数据输入有误。”

其次,程序在准确无误地运行之前,它可能有一些错误。例如,可能就会有这样的事情发生。

写代码的程序员才能决定后天是谁的生日。假如,今天是 3 月 3 号。程序会在当前日期的基础上加 2 天,找出所有 3 月 5 号出生的人。到目前为止,一切正常。

但到 3 月 30 号,程序会一个人也找不到,因为根本就没有 3 月 32 号。如果方法能够执行参数检查,那程序里就不会有那么多的错误。

“我记得我们讲 ArrayList 时,一起看过它的代码,get 和 set 方法里都有检查来确保索引参数比数组的长度大、相同或小。如果数组没有一个元素与索引相对应,代码就会抛出异常。

这是典型的输入检查。

3) 在类内更改代码错误较少。

假如我们写的类很有用,成为大项目中的一份子。大家都很喜欢这个类,以至于其他程序员开始在他们的代码中大量使用。

事实证明,这个类确实很有用,因此,你想让它更上一层楼。但如果你删去类里的任何一个方法,很多其他程序员的代码就不能再继续编译。他们需要快速重写他们的代码。改得越多,就越有可能发生错误。如果你经常改,你就越招人恨。

但如果我们改的是那些标为 private 的方法,我们就知道这些方法根本不会被别人的代码调用。我们可以重写,变更参数的数值和类型,而相依码依然可以运行。或者至少,它依然可以编译。

4) 我们可以定义其他对象如何与我们的对象交互。

我们可以限定针对对象可以执行哪些操作。例如,我们可能希望一个类只创建一个实例,即使我们是在同一个项目的多个地方同步创建。我们可以用封装来实现这一点。

封装 - 2

封装让我们可以应用额外的限定条件,来获得额外的优势。例如,String 类作为 immutable 对象实现。String 类的实例在创建和解构期间无法被更改。String 类的所有方法 (remove、substring…) 会返回一个新的字符串,而且不会更改它们所调用的对象。

“好厉害。这就是封装的运行原理。”

“封装太有趣了。”

“我也这么认为。”