《21天学通Java(第6版)》—— 1.5 组织类和类行为

1.5 组织类和类行为

21天学通Java(第6版)
Java面向对象编程还涉及另外三个概念:继承、接口和包,这些都是用于组织类和类行为的机制。

1.5.1 继承

继承是面向对象编程中最重要的概念之一,直接影响您如何设计和编写Java类。

继承是一种机制,让一个类能够继承另一个类的所有行为和属性。

通过继承,一个类可自动拥有现有类的所有功能,因此只需定义与现有类不同的地方。

通过继承,所有的类(无论是您创建的类,还是Java类库中的类)都以严格的层次结构来组织。

继承其他类的类叫子类,被继承的类叫超类。

一个类只能有一个超类,但可以有任意数目的子类。子类继承了其超类的所有属性和行为。

实际上,这意味着如果超类具备您的类所需的行为和属性,则无需重新定义或复制代码,便可获得同样的行为和属性。子类将自动从其超类那儿获得这些东西,而超类又从其超类获得相应的东西,依此类推。这样便形成了层次结构。子类将拥有层次结构中位于它上面所有类的特性,同时也有自己的特性。

这与您从父母那里继承各种东西(如身高、头发颜色、喜欢花生黄油和香蕉三明治)相同。它们也从其父母那里继承了一些特征,它们的父母又是从它们父母的父母那里继承,这样一直追溯到伊甸园、宇宙大爆炸或大爆炸之前。

图1.3显示了类的层次排列方式。

Java类层次结构的顶端是类Object。

所有的类都是从这个超类继承而来的。Object是层次结构中最通用的类,定义了Java类库中的所有类的行为。

在层次结构中越往下,类的用途越具体。在层次结构的顶部定义的是抽象概念,越往下,这些概念越具体。

使用Java创建新类时,常常希望它具备某个现有类的所有功能,并做一些修改。例如,您可能希望有一个新版本的CommandButton,能够在单击时发出声音。

要不经过任何重建工作而得到CommandButton的所有功能,可以将您的类定义为CommandButton的子类。

这样,您的类将自动继承CommandButton定义的行为和属性以及CommandButton的超类定义的行为和属性。您所需要关心的只是新类不同于CommandButton的内容。子类化(subclassing)机制用于定义新类及其与超类之间的差别。

子类化指的是通过继承已有的类来创建一个新类。子类只需指出其属性和行为不同于超类的地方。

如果您的类定义了全新的行为,且不是其他类的子类,则可以直接继承Object类。

如果您创建类时没有指定超类,Java将认为它直接继承Object。前面创建的VolcanoRobot类没有指定超类,因此是Object的子类。

1.5.2 创建类层次结构

如果您创建了大量的类,则应该让您的类从现有类层次结构继承,并构建自身的层次结构。这有如下优点:

可将多个类共有的功能放在一个超类中,这样就可以在更底层的类中重复使用这些功能;
对超类的修改将自动反映到其所有的子类、子类的子类等中,而无需修改或重新编译更底层的类,它们将通过继承获得新的信息。
例如,假设创建了一个Java类来实现火山勘测机器人的所有特征(这并不需要太多的想象力)。

该VolcanoRobot类已经完成,它工作正常,一切都很好。现在您在NASA的老板要求您创建一个名为MarsRobot的Java类。

这两种机器人有相似的特征:都是在恶劣环境下执行研究工作的机器人,且都跟踪其当前的温度和速度。

您首先想到的可能是,打开源代码文件VolcanoRobot.java,将其大部分代码复制到新的源代码文件MarsRobot.java,再根据新机器人的用途做必要的修改。

更好的办法是找出MarsRobot和VolcanoRobot的共同功能,并将它们放到一个更通用的类层次结构中。对于只有类VolcanoRobot和MarsRobot的情况,这也许是项繁重的工作,但如果您还想加入MoonRobot、UnderseaRobot和DesertRobot,情况将如何呢?将共同的行为放在一个或多个可重用的超类中将极大地减少所需完成的工作量。

要设计一个满足该目标的类层次,应从Object开始,它是所有Java类的祖宗。

这些机器人的老祖宗可能名为Robot。一般而言,机器人可被视为一种自控的探测设备。在Robot类中,您只定义使其成为自控的、用于探测的设备的行为。

在Robot下面有两个类:WalkingRobot和DrivingRobot。这两个类之间明显的区别在于,一个靠腿移动,另一个靠轮子移动。步行机器人的行为可能包括弯腰检东西、蹲下、跑动等。驱动式机器人的行为与此不同。图1.4显示了您目前已有的类层次结构。

现在,这个层次可以更具体。从WalkingRobot类可以派生出多个类:ScienceRobot、GuardRobot、SearchRobot等。另外,您可以抽取出更多的功能,创建两个中间类TwoLegged和FourLegged,其中每个类都有不同的行为(见图1.5)。

最后,整个层次结构便完成了,并为VolcanoRobot找到了合适的位置。它可以是ScienceRobot的子类,ScienceRobot是WalkingRobot的子类,WalkingRobot是Robot的子类,而Robot又是Object的子类。

诸如status、temperature和speed等属性应放在什么位置呢?应放在最合适的地方。因为所有机器人都需要跟踪其所处环境的温度,因此在Robot中将temperature定义为一个实例变量是合理的。这样所有的子类都将有这个实例变量。请记住,只需在层次结构定义行为或属性一次,它将自动被每个子类继承。

注意要设计出高效的类层次结构,需要做大量的规划和修订。当您试图将新的属性和行为加入到层次结构中时,很可能发现需要将一些类移到另一个位置,以便减少重复的特征和冗余的代码。

1.5.3 使用继承

在Java中,继承比现实生活中的继承要简单得多。Java中继承时,不需要遗嘱,也不需要法庭。

当您创建新对象时,Java将记录该对象及其超类的每个变量。这样,所有的类组合成当前对象的模板,每个对象都将包含合适的信息。

方法的工作原理与此相似,新对象可以访问其所属类及其超类的所有方法,这是在运行期间当方法被使用时动态确定的。如果您调用了特定对象的某个方法,Java虚拟机将首先检查该对象所属的类是否有该方法。如果没有,则在其超类中查找,依此类推,直到找到该方法的定义为止,如图1.6所示。

如果子类中定义了名称和其他方面都与超类相同的方法,情况将复杂起来。在这种情况下,首先被找到的方法是被使用的方法(从层次结构的底部开始向上查找)。

因此,可以在子类中创建一个方法来防止调用超类中定义的方法。为此,该方法的名称、返回值和参数必须与超类方法相同。这被称为覆盖,如图1.7所示。

注意 Java的继承形式称为单继承(single inheritance),因为每个Java类都只能有一个超类(虽然任何超类都可以有多个子类)。

在其他面向对象编程语言(如C++)中,类可以有多个超类,并继承所有超类的变量和方法,这叫多重继承(multiple inheritance)。Java只允许单继承,简化了继承机制。

1.5.4 接口

单继承简化了类之间的关系,并使这些类实现的功能更容易理解和设计。然而,它也有局限性,尤其是当您有一些相似的行为,它们需要在类层次结构的不同分支间进行复制时。Java通过使用接口来解决这些共享行为的问题。

接口是一组方法,它指出类除了从超类继承的行为外,还有其他行为。接口中的方法并没有定义行为,这项任务将由实现该接口的类去完成。

例如,Comparable接口包含一个这样的方法,即对属于同一个类的两个对象进行比较,以判断在排序链表中,哪个应在前面。任何实现了该接口的类都告诉其他对象,它能够确定其对象的排列顺序。如果没有该接口,类将不会有这种行为。

有关接口的内容将在第6章介绍。

1.5.6 包

在Java中,包用于将相关的类和接口编组,使得更容易在其他类中引用它们;包还避免了类之间潜在的命名冲突。

引用Java类时,可使用简短的名称,如Object,也可使用完整的名称,如java.lang.Object。

默认情况下,您的Java类只需通过简短的名称就可引用java.lang包中的类。java.lang包提供了基本的语言功能,如字符串处理和数学运算。要使用其他包中的类,必须使用完整的包名或使用import语句将包导入到源代码文件中。

例如,由于类Color位于包java.awt中,所以在程序中通常要使用java.awt.Color来引用它。

如果使用import语句导入了java.awt包,便可使用Color来引用这个类。

时间: 2024-08-22 14:20:21

《21天学通Java(第6版)》—— 1.5 组织类和类行为的相关文章

《21天学通Java(第6版)》—— 2.5 表达式和运算符

2.5 表达式和运算符 21天学通Java(第6版) 表达式是一条能够提供值的语句.最常见的是数学表达式,如下面的例子所示: 这3条语句都是表达式-它们提供了可被赋给变量的值.第1条语句将字面量3赋给变量x.第2条语句将变量x的值赋给变量y.在第3条语句中,乘法运算符*用来将x和y相乘,结果存储在变量z中. 表达式可以是任何变量.字面量和运算符的组合,也可以是方法调用,因为方法能够将一个值返回给调用它的类或对象. 您知道,表达式所提供的值称为返回值.在Java程序中,可将这个值赋给变量或以其他方

《21天学通Java(第6版)》—— 导读

前言 21天学通Java(第6版) 有些革命出其不意地吸引了全世界的眼球.Twitter.Linux操作系统和电视剧<Cupcake Wars>的异军突起颠覆了传统思维模式. 而Java语言的巨大成功却在人们的意料之中.自从Java语言于17年前面世以来,人们就对它充满殷切的期望.当Java融入到Web浏览器时,公众以无比的热情欢迎这种新语言的到来. Sun公司创始人Bill Joy在介绍这种新语言时,毫不掩饰其孤注一掷的心态:"15年来,我们一直力图开发出一种更佳的编程语言和环境,

《21天学通Java(第7版)》—— 2.2 变量和数据类型

2.2 变量和数据类型 在第1章创建的应用程序MarsRobot中,您使用变量来跟踪信息.变量是程序运行时能够存储信息的地方.可在程序的任何地方对其中的值进行修改--因此被称为变量. 要创建变量,必须提供名称并指定它存储的信息类型.还可以在创建变量的同时给它指定初始值. 在Java中,有3种变量:实例变量.类变量和局部变量. 正如第1章中指出的,实例变量用于定义对象的属性. 类变量定义类的属性,适用于类的所有实例. 局部变量用于方法定义乃至方法中更小的语句块中.仅当Java虚拟机执行这些方法或语

《21天学通Java(第6版)》—— 2.4 字面量

2.4 字面量 21天学通Java(第6版) 除变量外,还可以在Java语句中使用字面量.字面量可以是任何直接表示一个值的数字.文本或其他信息. 下面的赋值语句使用了字面量: 其中的字面量2012表示整数值2012.数字.字符和字符串都是字面量.Java有一些特殊类型的字面量,它们表示各种数字.字符.字符串和布尔值. 2.4.1 数字字面量 Java有几种整型字面量.例如,数字4是一个int类型的整型字面量,可将其赋给byte或short类型的变量,因为它足够小,在这些整数类型的取值范围内.位于

《21天学通Java(第6版)》—— 1.10 练习

1.10 练习 21天学通Java(第6版) 为巩固今天介绍的知识,请尝试完成下面的练习. 1.在VolcanoApplication类的main( )方法中,再创建一个名为virgil的VolcanoRobot对象,设置其实例变量,并将它们的值显示出来. 2.为国际象棋中的棋子创建一个继承层次结构,并决定在层次结构的什么位置定义实例变量color.startingPosition.forwardMovement和sideMovement.

《21天学通Java(第6版)》—— 1.4 属性和行为

1.4 属性和行为 21天学通Java(第6版)Java类包含两种不同的信息:属性和行为. 这两者在VolcanoRobot中都有,这是今天将作为类实现的项目.该项目使用计算机模拟火山探测工具,它模仿的是NASA的"遥控机器人研究"计划中用来在火山裂缝中进行研究探测的Dante II机器人. 创建该程序之前,您需要学习一些如何使用Java编写面向对象程序的知识.刚接触时,面向对象概念可能难以理解,但本书将给您提供大量将这些概念付诸实践的机会. 1.4.1 属性 属性(attribute

《21天学通Java(第6版)》—— 第 2 章 Java编程基础

第 2 章 Java编程基础 21天学通Java(第6版)Java程序是由类和对象组成的,而对象和类又是由方法和变量组成的.方法是由语句和表达式组成的,表达式又由运算符组成. 至此,您可能担心Java就像俄罗斯套娃.每个洋娃娃里边都有一个更小的洋娃娃,而后者同前者一样错综复杂. 本章将消除大洋娃娃的困扰,揭示Java编程的最小元素.本章暂时撇开类.对象和方法,介绍单行Java代码中的基本元素. 这包括以下内容: Java语句和表达式:变量和基本数据类型:常量:注释:字面量:算术运算符:比较运算符

《21天学通Java(第6版)》—— 1.7 问与答

1.7 问与答 21天学通Java(第6版)问:实际上,方法是在类中定义的函数.既然它们无论从外观和行为方面都类似于函数,为什么不将它们叫做函数呢? 答:有些面向对象编程语言确实将它们叫做函数(C++将它们叫做成员函数).其他一些面向对象语言将位于类(对象)内.外的函数区分开来,因为在这些语言中,使用不同的术语对理解每个函数的工作原理至关重要.因为其他语言有这种区别,同时术语"方法"在面向对象技术中很常用,所以Java也使用这个术语. 问:实例变量和实例方法同类变量和类方法之间有何区别

《21天学通Java(第6版)》—— 2.9 小测验

2.9 小测验 21天学通Java(第6版)请回答下述3个问题,以复习本章介绍的内容,答案见附录F. 1.下面哪个是合法的布尔值? A."false": B.false: C.10. 2.下面哪条不属于Java的变量命名约定? A.除第一个单词外,变量名中其他单词的首字母都大写: B.变量名的第一个字母小写: C.所有字母都大写. 3.下面哪种数据类型的取值范围为−32768-32767? A.char: B.byte: C.short.