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

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

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




    System。out。println(〃toy = 〃 + toy);  

    System。out。println(〃castille = 〃 + castille);  

  }  

  public static void main(String'' args) {  

    Bath b = new Bath();  

    b。print();  

  }  

} ///:~  

  

请注意在Bath 构建器中,在所有初始化开始之前执行了一个语句。如果不在定义时进行初始化,仍然不能保 

证能在将一条消息发给一个对象句柄之前会执行任何初始化——除非出现不可避免的运行期违例。  

下面是该程序的输出:  

  

Inside Bath()  

Soap()  

s1 = Happy  

s2 = Happy  

s3 = Joy  

s4 = Joy  

i = 47  

toy = 3。14  

castille = Constructed  

  

调用print()时,它会填充 s4,使所有字段在使用之前都获得正确的初始化。  



6。2 继承的语法  



继承与Java (以及其他OOP 语言)非常紧密地结合在一起。我们早在第 1 章就为大家引入了继承的概念,并 

在那章之后到本章之前的各章里不时用到,因为一些特殊的场合要求必须使用继承。除此以外,创建一个类 

时肯定会进行继承,因为若非如此,会从Java 的标准根类 Object 中继承。  



                                                                                           141 


…………………………………………………………Page 143……………………………………………………………

用于合成的语法是非常简单且直观的。但为了进行继承,必须采用一种全然不同的形式。需要继承的时候, 

我们会说:“这个新类和那个旧类差不多。”为了在代码里表面这一观念,需要给出类名。但在类主体的起 

始花括号之前,需要放置一个关键字extends,在后面跟随“基础类”的名字。若采取这种做法,就可自动 

获得基础类的所有数据成员以及方法。下面是一个例子:  

  

//: Detergent。java  

// Inheritance syntax & properties  

  

class Cleanser {  

  private String s = new String(〃Cleanser〃);  

  public void append(String a) { s += a; }  

  public void dilute() { append(〃 dilute()〃); }  

  public void apply() { append(〃 apply()〃); }  

  public void scrub() { append(〃 scrub()〃); }  

  public void print() { System。out。println(s); }  

  public static void main(String'' args) {  

    Cleanser x = new Cleanser();  

    x。dilute(); x。apply(); x。scrub();  

    x。print();  

  }  

}  

  

public class Detergent extends Cleanser {  

  // Change a method:  

  public void scrub() {  

    append(〃 Detergent。scrub()〃);  

    super。scrub(); // Call base…class version  

  }  

  // Add methods to the interface:  

  public void foam() { append(〃 foam()〃); }  

  // Test the new class:  

  public static void main(String'' args) {  

    Detergent x = new Detergent();  

    x。dilute();  

    x。apply();  

    x。scrub();  

    x。foam();  

    x。print();  

    System。out。println(〃Testing base class:〃);  

    Cleanser。main(args);  

  }  

} ///:~  

  

这个例子向大家展示了大量特性。首先,在Cleanser append()方法里,字串同一个 s 连接起来。这是用 

 “+=”运算符实现的。同“+”一样,“+=”被Java 用于对字串进行“过载”处理。  

其次,无论 Cleanser 还是Detergent 都包含了一个main()方法。我们可为自己的每个类都创建一个 

main()。通常建议大家象这样进行编写代码,使自己的测试代码能够封装到类内。即便在程序中含有数量众 

多的类,但对于在命令行请求的public 类,只有main()才会得到调用。所以在这种情况下,当我们使用 

 “java Detergent”的时候,调用的是Degergent。main()——即使Cleanser 并非一个public 类。采用这种 

将main()置入每个类的做法,可方便地为每个类都进行单元测试。而且在完成测试以后,毋需将main()删 

去;可把它保留下来,用于以后的测试。  

在这里,大家可看到Deteregent。main()对 Cleanser。main()的调用是明确进行的。  



                                                                                             142 


…………………………………………………………Page 144……………………………………………………………

需要着重强调的是Cleanser 中的所有类都是public 属性。请记住,倘若省略所有访问指示符,则成员默认 

为“友好的”。这样一来,就只允许对包成员进行访问。在这个包内,任何人都可使用那些没有访问指示符 

的方法。例如,Detergent 将不会遇到任何麻烦。然而,假设来自另外某个包的类准备继承Cleanser ,它就 

只能访问那些public 成员。所以在计划继承的时候,一个比较好的规则是将所有字段都设为private,并将 

所有方法都设为public (protected 成员也允许衍生出来的类访问它;以后还会深入探讨这一问题)。当 

然,在一些特殊的场合,我们仍然必须作出一些调整,但这并不是一个好的做法。  

注意Cleanser 在它的接口中含有一系列方法:append(),dilute(),apply(),scrub()以及print()。由于 

Detergent 是从Cleanser 衍生出来的(通过 extends 关键字),所以它会自动获得接口内的所有这些方法— 

—即使我们在 Detergent 里并未看到对它们的明确定义。这样一来,就可将继承想象成“对接口的重复利 

用”或者“接口的再生”(以后的实施细节可以自由设置,但那并非我们强调的重点)。  

正如在 scrub()里看到的那样,可以获得在基础类里定义的一个方法,并对其进行修改。在这种情况下,我 

们通常想在新版本里调用来自基础类的方法。但在 scrub()里,不可只是简单地发出对scrub()的调用。那样 

便造成了递归调用,我们不愿看到这一情况。为解决这个问题,Java 提供了一个 super 关键字,它引用当前 

类已从中继承的一个“超类”(Superclass)。所以表达式super。scrub()调用的是方法 scrub()的基础类版 

本。  

进行继承时,我们并不限于只能使用基础类的方法。亦可在衍生出来的类里加入自己的新方法。这时采取的 

做法与在普通类里添加其他任何方法是完全一样的:只需简单地定义它即可。extends 关键字提醒我们准备 

将新方法加入基础类的接口里,对其进行“扩展”。foam()便是这种做法的一个产物。  

在Detergent。main()里,我们可看到对于Detergent 对象,可调用Cleanser 以及Detergent 内所有可用的 

方法(如foam())。  



6。2。1  初始化基础类  



由于这儿涉及到两个类——基础类及衍生类,而不再是以前的一个,所以在想象衍生类的结果对象时,可能 

会产生一些迷惑。从外部看,似乎新类拥有与基础类相同的接口,而且可包含一些额外的方法和字段。但继 

承并非仅仅简单地复制基础类的接口了事。创建衍生类的一个对象时,它在其中包含了基础类的一个“子对 

象”。这个子对象就象我们根据基础类本身创建了它的一个对象。从外部看,基础类的子对象已封装到衍生 

类的对象里了。  

当然,基础类子对象应该正确地初始化,而且只有一种方法能保证这一点:在构建器中执行初始化,通过调 

用基础类构建器,后者有足够的能力和权限来执行对基础类的初始化。在衍生类的构建器中,Java 会自动插 

入对基础类构建器的调用。下面这个例子向大家展示了对这种三级继承的应用:  

  

//: Cartoon。java  

// Constructor calls during inheritance  

  

class Art {  

  Art() {  
返回目录 上一页 下一页 回到顶部 0 0
未阅读完?加入书签已便下次继续阅读!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!