实验6继承与接口文档格式.docx
《实验6继承与接口文档格式.docx》由会员分享,可在线阅读,更多相关《实验6继承与接口文档格式.docx(21页珍藏版)》请在冰豆网上搜索。
voidsetdata(Stringxm,intxh){//设置数据的方法
this.xm=xm;
this.xh=xh;
}
publicvoidprint(){//输出数据的方法
System.out.println(xm+"
"
+xh);
}
classTestStudent{//测试类
publicstaticvoidmain(String[]args){
Students=newStudent();
s.setdata("
小红"
2010242555);
s.print();
(2)编译源并运行程序。
贴图如下
图一
(二)创建将被继承的类
(1)程序功能:
通过Student类产生子类CollegeStudent,其不仅具有父类的成员变量xm(姓名)、xh(学号),还定义了新成员变量xy(学院)、bj(bj)。
在程序中调用了父类的print方法,同时可以看出子类也具有该方法。
程序代码:
publicclassCollegeStudentextendsStudent{
protectedStringxy;
protectedintbj;
voidsetdata(Stringxm,intxh,Stringxy,intbj){
super.setdata(xm,xh);
this.xy=xy;
this.bj=bj;
publicvoidprint(){
super.print();
System.out.print("
学院:
"
+xy+"
班级:
+bj);
}
classTestCollegeStudent{
CollegeStudentcs=newCollegeStudent();
cs.setdata("
小蓝"
2010242555,"
计算机学院"
1);
cs.print();
运行结果贴图:
图二
(三)了解成员方法的覆盖方式
(1)编写覆盖了Object类toString方法的一个类,并用System.out.println()输出该类的一个对象。
publicclassOverWriteToString{
privateStringstr;
publicOverWriteToString(){
publicOverWriteToString(Stringstr){
this.str=str;
publicStringToString(){
returnsuper.toString()+"
\n"
+str;
OverWriteToStringo=newOverWriteToString("
Thisisamethod"
+"
tooverwriteToStringmethod!
);
System.out.println(o.ToString());
图三
(2)试着以Point类为例,尝试为Object类的clone()和equals()方法进行覆盖,Point类包含私有成员x,y,构造方法1(包含两个参数a,b),构造方法2(参数为Pointp),clone方法,equals方法,toString方法。
用TestPoint类进行测试。
publicclassPoint{
privateintx;
privateinty;
publicPoint(){
publicPoint(inta,intb){
x=a;
y=b;
publicPoint(Pointp){
x=p.x;
y=p.y;
//重写equals()方法
publicbooleanequals(Objecto){
if(oinstanceofPoint){
return(x==((Point)o).x&
&
y==((Point)o).y);
else
returnfalse;
//重写toString()方法
publicStringtoString(){
\n该点的坐标为("
+x+"
"
+y+"
)"
;
//重写clone()方法
publicObjectclone()throwsCloneNotSupportedException{
returnnewPoint(this);
classTestPoint{
publicstaticvoidmain(String[]args)throwsCloneNotSupportedException{
Pointp=newPoint(2,3);
Pointp1=newPoint(p);
Pointp2=(Point)p.clone();
System.out.println("
p与p1相等吗?
+p.equals(p1));
p与p2相等吗?
+p.equals(p2));
System.out.println(p);
System.out.println(p1);
System.out.println(p2);
图四
(四)this、super和super()的使用
(1)程序功能:
说明this、super和super()的用法。
程序首先定义Point(点)类,然后创建点的子类Line(线)。
最后通过TestLine类输出线段的长度。
程序中通过super(a,b)调用父类Point的构造方法为父类的x和y赋值。
在子类Line的setLine方法中,因为参数名和成员变量名相同,为给成员变量赋值,使用this引用,告诉编译器是为当前类的成员变量赋值。
在length和toString方法中使用父类成员变量时,使用super引用,告诉编译器使用的是父类的成员变量。
publicclassLineextendsPoint{
privatePointp1;
privatePointp2;
publicLine(){
super(5,5);
publicLine(intx1,inty1,intx2,inty2){
p1=newPoint(x1,y1);
p2=newPoint(x2,y2);
publicLine(Pointp1,Pointp2){
this.p1=p1;
this.p2=p2;
publicvoidsetLine(Pointp1,Pointp2){
publicdoublelegth(){
returnMath.sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
\n该线起点为:
("
+p1.x+"
+p1.y+"
终点为:
+p2.x+"
+p2.y+"
classTestLine{
Pointp1=newPoint();
Pointp2=newPoint(3,4);
Linel=newLine(p1,p2);
System.out.println("
线l的长度为:
+l.legth());
System.out.println(l);
图五
(五)接口的实现与运用
实验任务:
本实验的任务是设计和实现一个Soundable接口,该接口具有发声功能,同时还能够调节声音大小。
Soundable接口的这些功能将会由3种声音设备来具体实现,它们分别是收音机Radio、随身昕Walkman和手机Mobilephone。
最后还要设计一个应用程序类来使用这些实现了Soundable接口的声音设备类。
程序运行时,先询问用户想听哪种设备,然后程序就会按照该设备的工作方式来发出声音。
实验步骤:
(1)仔细阅读程序,并完成其中的代码1~代码3。
//InterfaceTest.java
importjava.util.*;
interfaceSoundable{
publicvoidincreaseVolume();
publicvoiddecreaseVolume();
publicvoidstopSound();
publicvoidplaySound();
classRadioimplementsSoundable{
publicvoidincreaseVolume(){
增大收音机音量"
publicvoiddecreaseVolume(){
减小收音机音量"
publicvoidstopSound(){
关闭收音机"
publicvoidplaySound(){
收音机播放广播"
classWalkmanimplementsSoundable{
增大随声听音量"
减小随声听音量"
关闭随声听"
随声听播放音乐"
classMobilePhoneimplementsSoundable{
增大手机音量"
减小手机音量"
关闭手机"
手机播放铃声"
classPeople{
privateStringname;
privateintage;
publicvoidListen(Soundables){
s.playSound();
publicclassInterfaceTest{
inti;
Peoplesportsman=newPeople();
Scannerinput=newScanner(System.in);
Soundable[]soundDevice=newSoundable[3];
soundDevice[0]=newRadio();
soundDevice[1]=newWalkman();
soundDevice[2]=newMobilePhone();
你想听什么?
请输入选择(0——收音机,1——随声听,2——手机):
i=input.nextInt();
sportsman.Listen(soundDevice[i]);
soundDevice[i].increaseVolume();
soundDevice[i].stopSound();
(2)打开文本编辑器编辑InterfaceTest.java并保存,然后在Eclipse环境中进行编译,编译的结果将会产生6个class文件,其中包括Soundable.class,虽然Soundable本身是一个接口,但编译之后也会产生class文件。
(3)编译之后运行这个程序,观察所得结果。
图六
思考
(1)请问在InterfaceTest类中,SoundDevice[]数组是什么类型的,该数组为什么能存放3种不同的对象Radio、Walkman和Mobilephone呢?
答:
SoundDevice[]数组是接口类型;
因为类Radio、Walkman和Mobilephone都实现了接口SoundDevice,则接口SoundDevice就类似于这三个类的父类,而父类的引用可以指向一个子类的对象,所以该数组可以存放三个不同的对象。
(2)在程序中,Soundable是一个接口,那么该接口是否可以被实例化呢?
请在InterfaceTest类的main()方法中加入以下语句试验一下,并分析结果。
SoundableSound=newSoundable(),
图七
答:
不可以。
因为接口和抽象类相似,可以声明引用类型的变量,但不可使用new操作符创建接口的实例对象。
(3)现在假定要为程序增加一个闹钟类Clock,该类也实现Soundable接口,能够发出滴答声,请将以下的Clock类加入到InterfaceTest.java程序中,并在InterfaceTest类的main()方法中加入SoundDevice[3]=newClock();
语句。
classClockimplementsSoundable{
关闭闹钟"
闹钟发出滴答声"
修改之后,重新编译InterfaceTest.java并运行它,观察结果。
图八
(4)在第(3)小题中由于新加入的Clock类仅仅实现了Soundable接口的stopsound()和playsound()方法,而increaseVolume()和decreaseVolume()方法没有实现,因此它实质上是一个抽象类,而抽象类是不能实例化的,所以导致编译错误。
但是按照常理,闹钟的滴答声确实是不可以增大或减小的,那么如何解决这个问题呢?
现在请在Clock类中加入下面两个含{}空方法体的方法实现,再编译运行程序,看看会有什么变化。
publicvoidincreaseVolume(){}
publicvoiddecreaseVolume(){}
图九
(5)现在请模仿本实验的程序设计出一个自己的接口程序,要求先设计一个moveable可移动接口,然后分别设计3个类,即汽车Car、轮船Ship、飞机Aircraft来实现该接口,最后设计一个应用程序来使用它们。
interfaceMoveable{
publicabstractvoidmove();
classCarimplementsMoveable{
publicvoidmove(){
汽车行驶"
classShipimplementsMoveable{
publicvoidmove(){
轮船航行"
classAircraftimplementsMoveable{
飞机飞行"
publicclassTestMoveable{
Scannerinput=newScanner(System.in);
Moveable[]moveDevice=newMoveable[3];
moveDevice[0]=newCar();
moveDevice[1]=newShip();
moveDevice[2]=newAircraft();
您想乘坐什么?
请输入选择(0——汽车,1——轮船,2——飞机):
inti=input.nextInt();
Moveablem=moveDevice[i];
m.move();
input.close();
图十
实验分析:
接口的特点在于只定义能做什么,而不定义怎么去做。
在本实验中,收音机Radio,随身听Walkman和手机Mobilephone分别以自己的方式实现了Soundable接口,当接口成为Listen(Soundables)方法的形参时,任何实现了Soundable接口的对象都能成为它的实参,如果不用接口作形参,那就必须写3个不同的方法,即
listenRadio(Radior),
listenWalkman(Walkmanw),
listenMobilephone(Mobilephonem)。
课后作业题:
题11.1
图a的输出结果:
体现了构造方法链
图十一
图b编译问题:
父类构造方法并未被子类继承,当父类构造方法带形参时,在子类构造方法中应显示传递父类构造方法所需参数,且使用关键字super调用父类方法;
图十二
解决方法:
classA{
publicA(intx){
classBextendsA{
publicB(intx){
super(x);
publicclassC{
Bb=newB
(2);
图十三
题11.3
代码错误:
1.构造方法初始化类数据域时,由于参数名与数据域名相同,故数据域在构造方法中被隐藏,使用时应用关键字this来引用;
2.父类的构造方法是不被子类继承的,只能在子类的构造方法中使用关键字super调用;
3.调用父类中被覆盖的方法应使用关键字super来应用。
publicclassCircle{
privatedoubleradius;
publicCircle(doubleradius){
this.radius=radius;
publicdoublegetRadius(){
returnradius;
publicdoublegetArea(){
returnradius*radius*Math.PI;
classBextendsCircle{
privatedoublelength;
B(doubleradius,doublelength){
super(radius);
this.length=length;
returnsuper.getArea()*length;
classTestCircle{
Bb=newB(2,3);
半径为:
+b.getRadius());
面积为:
+b.getArea());
题11.5
如何在子类调用被覆盖的父类方法:
使用关键字super调用。
题11.7
如果子类中的一个方法具有和它父类中的方法完全相同的方法头,且返回值类型也相同,那么这是方法的覆盖。
题11.9
如果子类中的一个方法具有和它父类中的方法相同的名字,但参数类型不同,那么这是方法的重载。
题11.13
(1)true
(2)false(3)true(4)true(5)false(6)true(7)true(8)