think in java 第五章 隐藏实施过程

think in java 第五章的学习

包:库单元,Java访问指示符,接口与实现

 

第五章:隐藏实施过程

进行面向对象的设计时,一项基本的考虑是:如何将发生变化的东西与保持不变的东西分隔开。

具体情境如下:

我是一个java库的开发者,我的客户已经使用了我提供的资源库。我现在要修改扩充我的库,但是不能影响客户当前的功能(如果代码不稳定,客户代码要随着开发者的版本变化,那么这个库就是失败的,肯定没人用),要怎么解决这个问题呢?

最麻烦的是,作为一个java库的开发者,我不知道我的代码的哪个部分给客户调用了。我不能对代码进行修改和删除,假如我改动了客户正在调用的数据成员(方法,字段),那么客户的应用就完蛋了。

为了解决这个问题,我们可以这样想:我们需要实现权限管理,客户只能调用我们提供给客户的部分,而无权调用隐藏的部分。那么,在开发库时,我们可以保证客户调用的部分功能不变,而可以修改隐藏部分(实现过程)。这样就做到了间接修改实现过程。

1.包:库单元

比较简单的概念,所以稍微提及。

(1)创建独一无二的包名

报名不可冲突

(2)自定义工具库

创建自己的工具库

(3)利用导入改变行为

通过改变导入的package,我们可将自己的代码从调试版本变成最终的发行版本。这种技术可应用于任何种类的条件代码。

(4)包的停用

不使用包中的内容,就不要引用包,否则可能导致各种奇怪的问题。

2.Java访问指示符

针对类内每个成员的每个定义,Java访问指示符public,protected以及private都置于它们的最前面——无论它们是一个数据成员,还是一个方法。每个访问指示符都只控制着对那个特定定义的访问。

(1)友好的

如果根本不指定访问指示符,这时会出现什么情况呢?默认的访问没有关键字,但它通常称为“友好”(Friendly)访问。这意味着当前包内的其他所有类都能访问“友好的”成员,但对包外的所有类来说,这些成员却是“私有”(Private)的,外界不得访问。

1.使成员成为“public”(公共的)。这样所有人从任何地方都可以访问它。
2.变成一个“友好”成员,方法是舍弃所有访问指示符,并将其类置于相同的包内。这样一来,其他类就可以访问成员。
3.正如以后引入“继承”概念后大家会知道的那样,一个继承的类既可以访问一个protected成员,也可以访问一个public成员(但不可访问private成员)。只有在两个类位于相同的包内时,它才可以访问友好成员。但现在不必关心这方面的问题。
4.提供“访问器/变化器”方法(亦称为“获取/设置”方法),以便读取和修改值。这是OOP环境中最正规的一种方法,也是Java Beans的基础——具体情况会在第13章介绍。

我的理解:

这涉及到包的范围和成员,在决定成员作用域的时候需要注意,我一般不会用错。

(2)public:接口访问

使用public关键字时,它意味着紧随在public后面的成员声明适用于所有人,特别是适用于使用库的客户程序员。

举个例子:

两个方法,一个有public修饰,一个没有

因为两个类在不同的包下,所以test1这个没有public的方法报错了。test1的友好只限于在同一个包下,如果这两个类是在同一个包下,那么就不会报错。

我的理解:

public关键字非常常用,因为平时写逻辑经常都是有一堆方法需要调来调去的,我基本上都是写上的。但是一些不需要被包外调用方法就不需要加上public了,以后可以注意下。(但是我觉得基本上所有的方法都是需要经过测试的,所以写成public也好)

(3)private:不能接触!

private关键字意味着除非那个特定的类,而且从那个类的方法里,否则没有人能访问那个成员。同一个包内的其他成员不能访问private成员,这使其显得似乎将类与我们自己都隔离起来。另一方面,也不能由几个合作的人创建一个包。所以private允许我们自由地改变那个成员,同时毋需关心它是否会影响同一个包内的另一个类。

默认的“友好”包访问通常已经是一种适当的隐藏方法;请记住,对于包的用户来说,是不能访问一个“友好”成员的。这种效果往往能令人满意,因为默认访问是我们通常采用的方法。对于希望变成public(公共)的成员,我们通常明确地指出,令其可由客户程序员自由调用。而且作为一个结果,最开始的时候通常会认为自己不必频繁使用private关键字,因为完全可以在不用它的前提下发布自己的代码(这与C++是个鲜明的对比)。

然而,随着学习的深入,大家就会发现private仍然有非常重要的用途,特别是在涉及多线程处理的时候(详情见第14章)。

举个例子:

就算在同一包下,友好的方法是可以访问的,但是private的对象依然是不可以访问的。

我的理解:

很多时候,我会这样写实体类:

这时候使用对字段赋予private属性,只允许用方法与外界交互,可以实现很好的封装性,感觉很优雅。

private的重要性尤其体现在多线程开发中,常用于对私有对象的保护。这个将在多线程中详细讨论。

(3)protected:“友好的一种”

一点都不友好!涉及到继承的情况。我用得很少,所以不打算展开了。

3.接口与实现

我们通常认为访问控制是“隐藏实施细节”的一种方式。将数据和方法封装到类内后,可生成一种数据类型,它具有自己的特征与行为。但由于两方面重要的原因,访问为那个数据类型加上了自己的边界。第一个原因是规定客户程序员哪些能够使用,哪些不能。我们可在结构里构建自己的内部机制,不用担心客户程序员将其当作接口的一部分,从而自由地使用或者“滥用”。

这个原因直接导致了第二个原因:我们需要将接口同实施细节分离开。若结构在一系列程序中使用,但用户除了将消息发给public接口之外,不能做其他任何事情,我们就可以改变不属于public的所有东西(如“友好的”、protected以及private),同时不要求用户对他们的代码作任何修改。

我的理解:

这个大概就是我在文章开头的理解。

4.类访问

在Java中,亦可用访问指示符判断出一个库内的哪些类可由那个库的用户使用。若想一个类能由客户程序员调用,可在类主体的起始花括号前面某处放置一个public关键字。它控制着客户程序员是否能够创建属于这个类的一个对象。

为控制一个类的访问,指示符必须在关键字class之前出现。所以我们能够使用:
public class Widget {
也就是说,假若我们的库名是mylib,那么所有客户程序员都能访问Widget——通过下述语句:
import mylib.Widget;
或者
import mylib.*;

然而,我们同时还要注意到一些额外的限制:
(1) 每个编译单元(文件)都只能有一个public类。
(2) public类的名字必须与包含了编译单元的那个文件的名字完全相符。
(3) 如果有一个编译单元根本没有任何公共类。此时,可按自己的意愿任意指定文件名。

我的理解:

类的访问限制和方法几乎没有什么太大的不同,只是有了一些额外的限制。

5.总结

这章基本上很多都是已经掌握的,但是也巩固了我的概念。尤其是private在多线程中的重要性感觉特别重要。

发表评论

电子邮件地址不会被公开。 必填项已用*标注