第八章接口文档格式.docx
- 文档编号:22433963
- 上传时间:2023-02-04
- 格式:DOCX
- 页数:41
- 大小:110.30KB
第八章接口文档格式.docx
《第八章接口文档格式.docx》由会员分享,可在线阅读,更多相关《第八章接口文档格式.docx(41页珍藏版)》请在冰豆网上搜索。
8.1.2接口的定义
接口的定义包括接口声明和接口体两部分。
格式为:
<
修饰符>
interface<
接口名>
{
接口体
}
1.接口声明
接口声明的格式如下:
[public]interface接口名[extends父接口列表]
{
......
}
其中public指明任意类均可以使用这个接口,也可以省略。
省略时,接口使用默认的访问控制,即接口只能被与它处在同一包中的成员访问。
extends子句与类声明中的extends子句基本相同,不同的是一个接口可以有多个父接口,用逗号隔开,而一个类只能有一个父类。
子接口继承父接口中所有的常量和方法。
2.接口体
接口体中包含常量定义和方法定义两部分。
在接口中定义的常量默认具有public、final、static的属性。
常量定义的具体格式为:
typeNAME=value;
其中type可以是任意类型,NAME是常量名,通常用大写,value是常量值。
在接口
中定义的常量可以被实现该接口的多个类共享。
在接口中声明的方法默认具有public和abstract属性。
方法定义的格式为:
returnTypemethodName([Daramlist]);
在接口中的方法method只有定义没有实现,即接口中的方法都是抽象方法,所以实际上接口就是一种特殊的抽象类,这意味着在定义接口时不必考虑怎样实现接口。
【例8-1】声明接口。
本例声明了接口Student_info表示学生情况,其中有一个成员变量INSCHOOLYEAR和两个成员方法age和output。
程序如下:
interfaceStudent_info//学生情况接口
intINSCHOOLYEAR=2006;
intage();
voidoutput();
8.1.3接口的实现与使用
一旦定义了一个接口,一个或更多的类就能实现这个接口。
为了实现接口,类必须实现定义在接口中的方法,每个类能自由地决定方法具体实现的细节。
Java提倡充分地利用多态性中的“一个接口,多个方法”的特性。
接口的实现类似于继承,只是不用extends,而是用关键字implements声明一个类将实现一个接口,其声明格式如下:
[<
]class<
类名>
[extends<
超类名>
][implements<
接口名1>
,<
接口名2>
,…]
其中,<
可以是public,也可以省略。
如果一个类实现一个接口,则必须实现接口中的所有方法,且方法必须声明为public。
如果一个类实现多个接口,则用逗号分隔接口列表。
类的声明中用implements子句来表示一个类实现了某个接口,在类体中可以使用接口中定义的常量,而且必须实现接口中定义的所有方法。
一个类可以实现多个接口,在implements子句中用逗号分隔。
在类中实现接口所定义的方法时,方法的声明必须与接口中所定义的完全一致。
【例8-2】通过接口实现多态示例。
设计思路:
设计一个接口Shape,定义两个方法:
draw()、erase(),在Circle类、Square类和Triangle类的draw()方法、erase()方法具体实现这两个方法的功能。
代码:
//filename:
NewShapes.java
importjava.util.*;
//将Shape定义为interface
interfaceShape{
voiddraw();
voiderase();
//定义Circle类实现Shape
classCircleimplementsShape{
publicvoiddraw(){
System.out.println("
CallingCircle.draw()"
);
}
publicvoiderase(){
CallingCircle.erase()"
//定义Square类实现Shape
classSquareimplementsShape{
publicvoiddraw(){
CallingSquare.draw()"
CallingSquare.erase()"
//定义Triangle类实现Shape
classTriangleimplementsShape{
CallingTriangle.draw()"
CallingTriangle.erase()"
//包含main()的测试类
publicclassNewShapes{
staticvoiddrawOneShape(Shapes){
s.draw();
staticvoiddrawShapes(Shape[]ss){
for(inti=0;
i<
ss.length;
i++){
ss[i].draw();
}
publicstaticvoidmain(String[]args){
Randomrand=newRandom();
Shape[]s=newShape[9];
s.length;
switch(rand.nextInt(3)){
case0:
s[i]=newCircle();
break;
case1:
s[i]=newSquare();
case2:
s[i]=newTriangle();
}
drawShapes(s);
}
由本例可见,一个类实现一个接口,必须给出接口中所有方法的实现。
如果不能实现某方法,也必须写出一个空方法。
Java允许多个类实现同一个接口,这些类之间可以是毫无联系的,每个类各有自己实现方法的细节。
这一点与继承机制不同。
同时一个类也能实现多个接口,这就解决了多重继承的问题。
8.2抽象类
在Java中有一个与接口概念非常相似的概念,就是抽象类。
在定义一个类的时候,经常会碰到这样的情况:
有一些方法对于所有的对象都是合适的,但有些方法只对某个特定类型的对象才有意义。
这些方法在这个类中是不能实现的,把这种类定义为抽象类。
8.2.1什么是抽象类
抽象类往往用来表征在对问题领域进行分析、设计中得出的抽象概念,是对一系列看上去不同,但是本质上相同的具体概念的抽象。
例如,某些类在现实世界中是不能直接找到其对应的实例的,如车这个类,不可能为它找到一个对应的事物,因为现实世界中只有汽车、自行车、火车等事物,而它们都是车的子类,不能说是车这个类的实例,这样的类称为抽象(abstract)类。
Java允许在类中只声明方法而不提供方法的实现。
这种只有声明而没有方法体的方法称为抽象方法,而包含一个或多个抽象方法的类称为抽象类。
抽象类在使用上有特殊的限制,即不能创建抽象类的实例。
正是为了阻止程序员创建抽象类的实例对象,使编译器在编译时刻对此进行检查,Java中要将抽象类和抽象方法带上abstract标记。
如果抽象类的子类实现了抽象方法,则可以创建该子类的实例对象,否则该子类也是抽象类,也不能创建实例。
以abstract修饰的方法称抽象方法,所有的抽象方法都必须在抽象类或者接口中。
抽象方法只有方法头而无方法体,它定义的格式如下:
abstract返回值类型方法名([形参]);
//是否有形参,根据具体情况
例如:
abstractfloatacceleration(floata);
在这个定义中没有用大括号括起的方法体,只是说明有这样一个方法,名字是什么、返回值怎样、有什么形参,具体如何实现这个方法需要定义它的子类的任务。
抽象方法是为子类定义一个共同的形式上相同的接口,这样做的好处是使调用该方法的程序不必关心各个子类的内部情况,而实现相同的调用格式,达到简化程序,逻辑清晰的目的。
例如:
publicabstractclassshape
publicintr;
abstractpublicintarea();
这是一个抽象类shape,它提供了所有子类需要的属性和方法,其中的抽象方法area()是求面积(体积)的意思,它只是提供了这个类的对外接口的模式,至于它的子类怎么计算,与它无关。
而shape的非抽象子类,如Circle和Rectangle等都必须实现area()这个方法,但实现的方法体不一样,如Circle中是求面积,Rectangle中是求体积。
classCircleextendsshape
{
publicintr;
Circle(intr){this.r=r;
}
publicintarea(){return3*r*r;
classRectangleextendsshape
publicintwidth,height;
Rectangle(intw,inth)
width=w;
height=h;
publicintarea()
returnwidth*height;
抽象类中既存在抽象方法,也存在一般方法,如果一个父类是抽象类,其非抽象的子类如何继承它的方法呢?
抽象方法中一般方法的继承和普通的继承一样,只要该方法是非private的就可以继承。
而对于父类中的抽象方法是通过覆盖的形式来实现继承的。
就是在子类中定义一个与抽象方法有相同方法头的方法,并完成方法体的定义。
可以把这个过程称为“实现"
,即子类实现了抽象类的某个方法。
抽象类中可能有许多抽象方法,它的子类必须实现所有这些方法。
这样要求的原因是,如果子类不全部实现父类的抽象方法,子类中就存在了从父类继承来的抽象方法,这和抽象方法只存在于抽象类中的规定不符。
所以,如果子类没有实现全部的抽象方法,就必须仍定义为抽象类。
这一点和接口的实现一样。
而如果抽象类的子类也是抽象类,子类也可以去实现父类的抽象方法或定义更多的抽象方法,很灵活。
8.2.2抽象类的作用
我们在上节接口中给出了一个关于几何形状Shape及其子类的例子。
在这个类的层次结构中,Shape类是顶层类。
实际上Shape类的对象是没有实际意义的。
定义Shape类的目的并不是为了在程序中创建并操作它的对象,而是为了定义几何形状类体系的通用接口,例如draw()和erase(),这些接口在Shape类中不需要给出具体实现,而由它的各个子类提供自己的实现。
因此Shape类可以定义为抽象类,而draw()和erase()方法可以定义为抽象方法,如图8-2所示。
图8-2抽象类Shape及其类体系
实际上,即使不包括任何抽象方法,也可将一个类声明为抽象类。
这样的类往往是没有必要定义任何抽象方法,而设计者又想禁止创建该类的实例对象,此时只需在类的声明中加上abstract关键词。
定义抽象类和抽象方法可以向用户和编译器明确表明该类的作用和用法,使类体系设计更加清晰,并能够支持多态,因此是Java的一种很有用的面向对象机制。
8.2.3接口与抽象类
通过上述对抽象类和接口的介绍,我们可以发现接口与抽象类有一定的相似性,但实际上这二者之间有很大的区别:
●接口中的所有方法都是抽象的,而抽象类可以定义带有方法体的不同方法。
●一个类可以实现多个接口,而只能继承一个抽象父类。
●接口与实现它的类不构成类的继承体系,即接口不是类体系的一部分。
因此,不相关的类也可以实现相同的接口。
而抽象类是属于一个类的继承体系,并且一般位于类体系的顶层。
使用接口的主要优势在于:
一是类通过实现多个接口可以实现多重继承,这是接口最重要的作用,也是使用接口的最重要的原因,能够使子类对象上溯造型为多个基础类(接口)类型;
二是能够抽象出不相关类之间的相似性,而没有强行形成类的继承关系。
使用接口,可以同时获得抽象类以及接口的优势。
所以如果要创建的类体系的基础类不需要定义任何成员变量,并且不需要给出任何方法的完整定义,则应该将基础类定义为接口。
只有在必须使用方法定义或成员变量时,才应该考虑采用抽象类。
8.3包
8.3.1什么是包
我们都熟悉Windows的文件组织方式:
文件夹。
同一文件夹中的文件不能重名,不同文件夹中的文件可以重名,如果没有文件夹的存在,将文件全部放在一起,则要求所有文件名必须是惟一的,否则会发生命名冲突,而且文件存放没有层次,杂乱无章。
如果将相关文件按文件夹分门别类存放,则显得井井有条,便于查找,而且文件夹中还可以有子文件夹。
同样地,如果编写的程序代码较繁杂,参加编写的人员较多,很可能由于类的命名和引用问题引发冲突。
为此,Java提供了一种叫做“包(Package)”的机制,从而避免了命名冲突的发生。
所谓“包”就是一个区别类名字空间的机制,它是Java提供的类的组织方式。
包对应一个文件夹,包中还可以有包,称为包等级。
定义的类都加入某一个包中,并作为包的一部分存在,Java类中的成员变量和成员方法都在类中定义,使用包机制使每个Java的变量和方法都可以用全限定的名字来表示,即包括包名、类名和成员(方法和变量)名,各部分间用点号分隔即可。
简单地说,如果两个不同的程序员编写的代码在命名上有重复,又被放在了同一个名称空间内,必然会引发冲突。
但包机制的引入将这些同名的标识符放在了不同的名称空间内,这样在使用时就可以很方便地区分,不会引发冲突了。
如果源程序中没有声明类所在的包,Java将类放在默认的包中,这意味着每个类必须使用惟一的名字,否则会发生名字冲突,就像Windows同一文件夹中的同名文件一样。
在Java语言中,包的作用是很大的。
包是实现封装的一种手段,也是限定类中方法和变量的作用域的一种手段。
它为类和其他的子包提供了一个“容器”。
这个容器针对不同的访问级别来确定具体的访问范围。
当类被声明为public时,其代码可以被任何其他代码访问;
而类的访问控制设为默认时(即没有显式表明),则相当于friendly,可以被同一包中的其他代码访问。
也就是说,定义类时如果没有设置访问修饰符,这些类可以被该类所在包的其他类所访问,而对除此之外的所有类都不可见。
创建一个包非常简单,在Java源文件的最开始处包含一个package语句即可。
包含package关键词的声明语法格式为:
package包名;
package语句定义了一个存放类的命名空间,所有使用相同包名称的类都被归在同一个包中。
如果没有package语句,类的名字被放进一个默认的包中,该包没有名字。
由于类和类成员的可访问性含有包的控制因素在内,所以建议大家尽量使用包。
Java平台中的类与接口都是根据功能以包组织的。
Java的JDK提供的包主要有:
java.lang语言包
java.util实用包
java.awt抽象窗口工具包
java.text文本包
java.io输入输出流的文件包
java.appletapplet应用程序
网络功能
每个包中都定义了许多功能相关的类和接口。
我们也可以定义自己的包来实现自己的应用程序。
Java编译器把包对应于文件系统的目录和文件管理,还可以使用ZIP或JAR压缩文件的形式保存。
例如,以Windows平台为例,名为java.applet的包中,所有类文件都存储在目录classPath\java\applet下。
其中包根目录——classPath由环境变量CLASSPATH来设定。
8.3.2包的定义与使用
1.包的定义
使用package语句指定一个源文件中的类属于一个特定的包。
Package语句的格式如下:
packagepkgl[.pkg2[.pkg3…]];
下面以具体例子来介绍包的定义和引用。
packagePackageTest;
publicclassHello
Stringhello1;
Stringhello2;
publicHello()
hello1="
Hello"
;
hello2="
World"
publicvoidprintHello()
System.out.print(hello1);
System.out.println(hello2);
这样就创建了一个PackageTest包,其中包含一个Hello类。
Hello类成为PackageTest包中的一个public成员,并存放在classPath\PackageTest目录中。
如果源文件中没有package语句,则指定为无名包。
无名包没有路径,一般情况下,会把源文件中的类存储在当前目录(即存放Java源文件的目录)下。
前面许多例子都属于这种情况。
说明:
●package语句在每个Java源程序中只能有一条,一个类只能属于一个包。
●package语句必须在程序的第1行,该行前可有空格及注释行。
●包名以“.”为分隔符。
2.包的使用
在Java中引入包(例如JDK中的包或用户自定义的包)中的类是通过import语句实现的。
Import语句的格式如下:
importpkgl[.pkg2[,.pkg3.…]].(classname|*);
其中pkgl[.pkg2[.pkg3…]]表明包的层次,与package语句相同,它对应于文件目录,classname则是要引入的类名。
如果要从一个包中引入多个类,则可以用通配符(*)来代替。
例如下列代码引入util包中的Date类:
importjava.util.Date;
//引入util包中的Date类
Datedate1=newDate();
//直接使用Date类
下例引入util包中的所有类,程序中便可以直接引用该包中的任意类:
//引入graphics包中的所有类
Vectorv=newVector();
//直接使用Vector类
注意:
import语句必须在源程序任何类声明之前,在package语句之后。
因此Java程序的一般结构如下:
[package语句]//默认是package.;
(属于当前目录)
[import语句]//默认是importjava.lang.*;
[类声明]
//直接使用Date类
3.包定义与使用示例
【例8-3】定义二维几何图形的包并使用。
⑴文件Rectangle.java,定义了Rectangle类放入MyPackageTwoD包中。
packageMyPackageTwoD;
publicclassRectangle
publicintwidth=0;
publicintheight=0;
publicPointorigin;
publicRectangle(Pointp,intw,inth)
origin=p;
width=w;
height=h;
publicvoidmove(intx,inty)
origin.x=x;
origin.y=y;
returnwidth*height;
⑵文件Point.java,定义了Point类放入MyPackageTwoD包中
publicclassPoint
publicintx=0;
publicinty=0;
publicPoint(intx,inty)
this.x=x;
this.y=y;
⑶文件TestPackage.java,包含ma
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 第八 接口
![提示](https://static.bdocx.com/images/bang_tan.gif)