友情提示:如果本网页打开太慢或显示不完整,请尝试鼠标右键“刷新”本网页!阅读过程发现任何错误请告诉我们,谢谢!! 报告错误
一世书城 返回本书目录 我的书架 我的书签 TXT全本下载 进入书吧 加入书签

Java编程思想第4版[中文版](PDF格式)-第55章

按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!




    return ps1;  

  }  

  public void f() {}  

}  

  

class Sandwich { // Uses Lunch  

  void f() { new Lunch(); }  



                                                                                    135 


…………………………………………………………Page 137……………………………………………………………

}  

  

// Only one public class allowed per file:  

public class Lunch {  

  void test() {  

    // Can't do this! Private constructor:  

    //! Soup priv1 = new Soup();  

    Soup priv2 = Soup。makeSoup();  

    Sandwich f1 = new Sandwich();  

    Soup。access()。f();  

  }  

} ///:~  

  

④:实际上,Java 1。1 内部类既可以是“受到保护的”,也可以是“私有的”,但那属于特别情况。第 7 章 

会详细解释这个问题。  

  

⑤:亦可通过从那个类继承来实现。  

  

迄今为止,我们创建过的大多数方法都是要么返回 void,要么返回一个基本数据类型。所以对下述定义来 

说:  

  

public static Soup access() {  

return psl;  

}  

  

它最开始多少会使人有些迷惑。位于方法名(access)前的单词指出方法到底返回什么。在这之前,我们看 

到的都是void,它意味着“什么也不返回”(void 在英语里是“虚无”的意思。但亦可返回指向一个对象的 

句柄,此时出现的就是这个情况。该方法返回一个句柄,它指向类Soup 的一个对象。  

Soup 类向我们展示出如何通过将所有构建器都设为 private,从而防止直接创建一个类。请记住,假若不明 

确地至少创建一个构建器,就会自动创建默认构建器(没有自变量)。若自己编写默认构建器,它就不会自 

动创建。把它变成 private 后,就没人能为那个类创建一个对象。但别人怎样使用这个类呢?上面的例子为 

我们揭示出了两个选择。第一个选择,我们可创建一个static 方法,再通过它创建一个新的 Soup,然后返 

回指向它的一个句柄。如果想在返回之前对Soup 进行一些额外的操作,或者想了解准备创建多少个 Soup 对 

象(可能是为了限制它们的个数),这种方案无疑是特别有用的。  

第二个选择是采用“设计方案”(Design Pattern)技术,本书后面会对此进行详细介绍。通常方案叫作 

 “独子”,因为它仅允许创建一个对象。类Soup 的对象被创建成Soup 的一个 static private 成员,所以有 

一个而且只能有一个。除非通过public 方法access(),否则根本无法访问它。  

正如早先指出的那样,如果不针对类的访问设置一个访问指示符,那么它会自动默认为“友好的”。这意味 

着那个类的对象可由包内的其他类创建,但不能由包外创建。请记住,对于相同目录内的所有文件,如果没 

有明确地进行package 声明,那么它们都默认为那个目录的默认包的一部分。然而,假若那个类一个static 

成员的属性是public,那么客户程序员仍然能够访问那个static 成员——即使它们不能创建属于那个类的 

一个对象。  



5。5 总结  



对于任何关系,最重要的一点都是规定好所有方面都必须遵守的界限或规则。创建一个库时,相当于建立了 

同那个库的用户(即“客户程序员”)的一种关系——那些用户属于另外的程序员,可能用我们的库自行构 

建一个应用程序,或者用我们的库构建一个更大的库。  

如果不制订规则,客户程序员就可以随心所欲地操作一个类的所有成员,无论我们本来愿不愿意其中的一些 

成员被直接操作。所有东西都在别人面前都暴露无遗。  

本章讲述了如何构建类,从而制作出理想的库。首先,我们讲述如何将一组类封装到一个库里。其次,我们 

讲述类如何控制对 自己成员的访问。  

一般情况下,一个 C 程序项目会在 50K 到 100K 行代码之间的某个地方开始中断。这是由于 C 仅有一个“命名 



                                                                              136 


…………………………………………………………Page 138……………………………………………………………

空间”,所以名字会开始互相抵触,从而造成额外的管理开销。而在Java 中,package 关键字、包命名方案 

以及import关键字为我们提供对名字的完全控制,所以命名冲突的问题可以很轻易地得到避免。  

有两方面的原因要求我们控制对成员的访问。第一个是防止用户接触那些他们不应碰的工具。对于数据类型 

的内部机制,那些工具是必需的。但它们并不属于用户接口的一部分,用户不必用它来解决自己的特定问 

题。所以将方法和字段变成“私有”(private)后,可极大方便用户。因为他们能轻易看出哪些对于自己来 

说是最重要的,以及哪些是自己需要忽略的。这样便简化了用户对一个类的理解。  

进行访问控制的第二个、也是最重要的一个原因是:允许库设计者改变类的内部工作机制,同时不必担心它 

会对客户程序员产生什么影响。最开始的时候,可用一种方法构建一个类,后来发现需要重新构建代码,以 

便达到更快的速度。如接口和实施细节早已进行了明确的分隔与保护,就可以轻松地达到自己的目的,不要 

求用户改写他们的代码。  

利用Java 中的访问指示符,可有效控制类的创建者。那个类的用户可确切知道哪些是自己能够使用的,哪些 

则是可以忽略的。但更重要的一点是,它可确保没有任何用户能依赖一个类的基础实施机制的任何部分。作 

为一个类的创建者,我们可自由修改基础的实施细节,这一改变不会对客户程序员产生任何影响,因为他们 

不能访问类的那一部分。  

有能力改变基础的实施细节后,除了能在以后改进自己的设置之外,也同时拥有了“犯错误”的自由。无论 

当初计划与设计时有多么仔细,仍然有可能出现一些失误。由于知道自己能相当安全地犯下这种错误,所以 

可以放心大胆地进行更多、更自由的试验。这对自己编程水平的提高是很有帮助的,使整个项目最终能更 

快、更好地完成。  

一个类的公共接口是所有用户都能看见的,所以在进行分析与设计的时候,这是应尽量保证其准确性的最重 

要的一个部分。但也不必过于紧张,少许的误差仍然是允许的。若最初设计的接口存在少许问题,可考虑添 

加更多的方法,只要保证不删除客户程序员已在他们的代码里使用的东西。  



5。6  练习  



(1) 用public、private、protected 以及“友好的”数据成员及方法成员创建一个类。创建属于这个类的一 

个对象,并观察在试图访问所有类成员时会获得哪种类型的编译器错误提示。注意同一个目录内的类属于 

 “默认”包的一部分。  

(2) 用protected 数据创建一个类。在相同的文件里创建第二个类,用一个方法操纵第一个类里的 

protected 数据。  

(3) 新建一个目录,并编辑自己的 CLASSPATH,以便包括那个新目录。将P。class 文件复制到自己的新目 

录,然后改变文件名、P 类以及方法名(亦可考虑添加额外的输出,观察它的运行过程)。在一个不同的目 

录里创建另一个程序,令其使用自己的新类。  

(4) 在 c05 目录(假定在自己的CLASSPATH 里)创建下述文件:  

  

//: PackagedClass。java  

package c05;  

class PackagedClass {  

  public PackagedClass() {  

    System。out。println(  

      〃Creating a packaged class〃);  

  }  

} ///:~  

  

然后在 c05 之外的另一个目录里创建下述文件:  

  

//: Foreign。java  

package c05。foreign;  

import c05。*;  

public class Foreign {  

   public static void main (String'' args) {  

      PackagedClass pc = new PackagedClass();  

   }  



                                                                            137 


…………………………………………………………Page 139……………………………………………………………

} ///:~  

  

解释编译器为什么会产生一个错误。将Foreign (外部)类作为c05 包的一部分改变了什么东西吗?  



                                                                                          138 


…………………………………………………………Page 140……………………………………………………………

                                  第 6 章  类再生  



  

 “Java 引人注目的一项特性是代码的重复使用或者再生。但最具革命意义的是,除代码的复制和修改以外, 

我们还能做多得多的其他事情。”  

  

在象C 那样的程序化语言里,代码的重复使用早已可行,但效果不是特别显著。与Java 的其他地方一样,这 

个方案解决的也是与类有关的问题。我们通过创建新类来重复使用代码,但却用不着重新创建,可以直接使 

用别人已建好并调试好的现成类。  

但这样做必须保证不会干扰原有的代码。在这一章里,我们将介绍两个达到这一目标的方法。第一个最简 

单:在新类里简单地创建原有类的对象。我们把这种方法叫作“合成”,因为新类由现有类的对象合并而 

成。我们只是简单地重复利用代码的功能,而不是采用它的形式。  

第二种方法则显得稍微有些技巧。它创建一个新类,将其作为现有类的一个“类型”。我们可以原样采取现 

有类的形式,并在其中加入新代码,同时不会对现有的类产生影响。这种魔术般的行为叫作“继承” 

 (Inheritance),涉及的大多数工作都是由编译器完成的。对于面向对象的程序设计,“继承”是最重要的 

基础概念之一。它对我们下一章要讲述的内容会产生一些额外的影响。  

对于合成与继承这两种方法,大多数语法和行为都是类似的(因为它们都要根据现有的类型生成新类型)。 

在本章,我们将深入学习这些代码再生或者重复使用的机制。  



6。1 合成的语法  



就以前的学习情况来看,事实上已进行了多次“合成”操作。为进行合成,我们只需在新类里简单地置入对 

象句柄即可。举个例子来说,假定需要在一个对象里容纳几个 String 对象、两种基本数据类型以及属于另一 

个类的一个对象。对于非基本类型的对象来说,只需将句柄置于新类即可;而对于基本数据类型来说,则需 

在自己的类中定义它们。如下所示(若执行该程序时有麻烦,请参见第
返回目录 上一页 下一页 回到顶部 0 0
未阅读完?加入书签已便下次继续阅读!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!