Java编程思想-第7章 复用类(要点)

  复用代码是Java众多引人注目的功能之一。但要想成为极具革命性的语言,仅仅能够复制 代码并对之加以改变是不够的,它还必须能够做更多的事情。

  上述方法常为C这类过程型语言所使用,但收效并不是很好。正如Java中所有事物一样,问 题解决都是围绕着类展开的。可以通过创建新类来复用代码,而不必再重头开始编写。可以使 用别人业已开发并调试好的类。 此方法的窍门在于使用类而不破坏现有程序代码。读者将会在本章中看到两种达到这一目 的的方法。第一种方法非常直观:只需在新的类中产生现有类的对象。由于新的类是由现有 类的对象所组成,所以这种方法称为组合。该方法只是复用了现有程序代码的功能,而非它 的形式。 第二种方法则更细致一些,它按照现有类的类型来创建新类。无需改变现有类的形式,采 用现有类的形式并在其中添加新代码。这种神奇的方式称为继承,而且编译器可以完成其中大 部分工作。继承是面向对象程序设计的基石之一,我们将在第8章中探究其含义与功能。 就组合和继承而言,其语法和行为大多是相似的。由于它们是利用现有类型生成新类型, 所以这样做极富意义。在本章中,读者将会了解到这两种代码重用机制。

7.1 组合语法

  本书到目前为止,已多次使用组合技术。只需将对象引用置于新类中即可。例如,假设你 需要某个对象,它要具有多个 String对象、几个基本类型数据,以及另一个类的对象。对于非基 本类型的对象,必须将其引用置于新的类中,但可以直接定义基本类型数据。

7.2 继承语法

  继承是所有OOP语言和Java语言不可缺少的组成部分。当创建一个类时,总是在继承,因 此,除非已明确指出要从其他类中继承,否则就是在隐式地从Java的标准根类 Object进行继承 组合的语法比较平实,但是继承使用的是一种特殊的语法。在继承过程中,需要先声明 “新类与旧类相似”。这种声明是通过在类主体的左边花括号之前,书写后面紧随基类名称的关 键字 extends而实现的。当这么做时,会自动得到基类中所有的域和方法。

7.2.1 初始化基类

7.3 代理

  第三种关系称为代理,Java并没有提供对它的直接支持。这是继承与组合之间的中庸之道,因为 我们将一个成员对象置于所要构造的类中(就像组合),但与此同时我们在新类中暴露了该成员 对象的所有方法(就像继承)。

7.4 结合使用组合和继承

7.4.1  确保正确清理

7.4.2 名称屏蔽

7.5 在组合与继承之间选择

7.6 protected关键字

7.7 向上转型

  为新的类提供方法”并不是继承技术中最重要的方面,其最重要的方面是用来表现新类和 基类之间的关系。这种关系可以用“新类是现有类的一种类型”这句话加以概括。

7.8 final关键字

  根据上下文环境,Java的关键字fna的含义存在着细微的区别,但通常它指的是“这是无法 改变的。”不想做改变可能出于两种理由:设计或效率。由于这两个原因相差很远,所以关键字 final有可能被误用。 以下几节谈论了可能使用到final的三种情况:数据、方法和类。

  空白final

   Java允许生成“空白 final”,所谓空白fnal是指被声明为final但又未给定初值的域。无论什 么情况,编译器都确保空白 final在使用前必须被初始化。但是,空白final在关键字final的使用 上提供了更大的灵活性,为此,一个类中的 final域就可以做到根据对象而有所不同,却又保持 其恒定不变的特性。

  final和 private关键字

   类中所有的 private方法都隐式地指定为是final的。由于无法取用 private方法,所以也就无 法覆盖它。可以对 private方法添加fnal修饰词,但这并不能给该方法增加任何额外的意义。 覆盖”只有在某方法是基类的接口的一部分时才会出现。即,必须能将一个对象向上转型 为它的基本类型并调用相同的方法(这一点在下一章阐明)。如果某方法为 private,它就不是基 类的接口的一部分。它仅是一些隐藏于类中的程序代码,只不过是具有相同的名称而已。但如 果在导出类中以相同的名称生成一个 public、 protected或包访问权限方法的话,该方法就不会产 生在基类中出现的“仅具有相同名称”的情况。此时你并没有覆盖该方法,仅是生成了一个新 的方法。由于 private方法无法触及而且能有效隐藏,所以除了把它看成是因为它所归属的类的 组织结构的原因而存在外,其他任何事物都不需要考虑到它。

7.9 初始化及类的加载

  在许多传统语言中,程序是作为启动过程的一部分立刻被加载的。然后是初始化,紧接着 程序开始运行。这些语言的初始化过程必须小心控制,以确保定义为 static的东西,其初始化顺 序不会造成麻烦。例如C++中,如果某个 static期望另一个 static在被初始化之前就能有效地使用 它,那么就会出现问题。 Java就不会出现这个问题,因为它采用了一种不同的加载方式。加载是众多变得更加容易 的动作之一,因为Java中的所有事物都是对象。请记住,每个类的编译代码都存在于它自己的 独立的文件中。该文件只在需要使用程序代码时才会被加载。一般来说,可以说:“类的代码在 初次使用时才加载。”这通常是指加载发生于创建类的第一个对象之时,但是当访问 static域或 static方法时,也会发生加载。 初次使用之处也是 static初始化发生之处。所有的 static对象和 static代码段都会在加载时依 程序中的顺序(即,定义类时的书写顺序)而依次初始化。当然,定义为 static的东西只会被初 始化一次。

7.10总结

  继承和组合都能从现有类型生成新类型。组合一般是将现有类型作为新类型底层实现的 部分来加以复用,而继承复用的是接口 在使用继承时,由于导出类具有基类接口,因此它可以向上转型至基类,这对多态来讲至 关重要,就像我们将在下一章中将要看到的那样。 尽管面向对象编程对继承极力强调,但在开始一个设计时,一般应优先选择使用组合(或 者可能是代理),只在确实必要时才使用继承。因为组合更具灵活性。此外,通过对成员类型使 用继承技术的添加技巧,可以在运行时改变那些成员对象的类型和行为。因此,可以在运行时 改变组合而成的对象的行为。

posted @ 2018-03-02 11:30  JackYgy  阅读(110)  评论(0)    收藏  举报