实验6继承与接口.docx
- 文档编号:10332947
- 上传时间:2023-02-10
- 格式:DOCX
- 页数:21
- 大小:195.39KB
实验6继承与接口.docx
《实验6继承与接口.docx》由会员分享,可在线阅读,更多相关《实验6继承与接口.docx(21页珍藏版)》请在冰豆网上搜索。
实验6继承与接口
山西大学计算机与信息技术学院
实验报告
姓名
学号
专业班级
课程名称
Java实验
实验日期
成绩
指导教师
批改日期
实验名称
实验6继承与接口
[实验目的]
1、掌握java继承中父类及其子类的定义方法。
2、掌握子类重写父类同名方法的方法。
3、掌握接口的用法。
(1)学习如何定义接口;
(2)掌握接口的实现方式;
(3)使用实现了接口的类;
(4)理解接口与抽象类的区别。
[实验要求]
1、复习理论教学中所学的内容。
2、认真进行实验预习,查阅参考书,书写源程序,书写实验预习报告。
3、认真总结实验并书写实验报告。
[实验内容]
1、类的继承性练习
(1)程序源代码如下。
publicclassStudent{
protectedStringxm;//姓名,具有保护修饰符的成员变量
protectedintxh;//学号
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{
publicstaticvoidmain(String[]args){
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;
}
publicstaticvoidmain(String[]args){
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(){
returnsuper.toString()+"\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));
System.out.println("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){
super(5,5);
p1=newPoint(x1,y1);
p2=newPoint(x2,y2);
}
publicLine(Pointp1,Pointp2){
super(5,5);
this.p1=p1;
this.p2=p2;
}
publicvoidsetLine(Pointp1,Pointp2){
this.p1=p1;
this.p2=p2;
}
publicdoublelegth(){
returnMath.sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
}
publicStringtoString(){
returnsuper.toString()+"\n该线起点为:
("+p1.x+","+p1.y+")"
+"终点为:
("+p2.x+","+p2.y+")";
}
}
classTestLine{
publicstaticvoidmain(String[]args){
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(){
System.out.println("增大收音机音量");
}
publicvoiddecreaseVolume(){
System.out.println("减小收音机音量");
}
publicvoidstopSound(){
System.out.println("关闭收音机");
}
publicvoidplaySound(){
System.out.println("收音机播放广播");
}
}
classWalkmanimplementsSoundable{
publicvoidincreaseVolume(){
System.out.println("增大随声听音量");
}
publicvoiddecreaseVolume(){
System.out.println("减小随声听音量");
}
publicvoidstopSound(){
System.out.println("关闭随声听");
}
publicvoidplaySound(){
System.out.println("随声听播放音乐");
}
}
classMobilePhoneimplementsSoundable{
publicvoidincreaseVolume(){
System.out.println("增大手机音量");
}
publicvoiddecreaseVolume(){
System.out.println("减小手机音量");
}
publicvoidstopSound(){
System.out.println("关闭手机");
}
publicvoidplaySound(){
System.out.println("手机播放铃声");
}
}
classPeople{
privateStringname;
privateintage;
publicvoidListen(Soundables){
s.playSound();
}
}
publicclassInterfaceTest{
publicstaticvoidmain(String[]args){
inti;
Peoplesportsman=newPeople();
Scannerinput=newScanner(System.in);
Soundable[]soundDevice=newSoundable[3];
soundDevice[0]=newRadio();
soundDevice[1]=newWalkman();
soundDevice[2]=newMobilePhone();
System.out.println("你想听什么?
请输入选择(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{
publicvoidstopSound(){
System.out.println("关闭闹钟");
}
publicvoidplaySound(){
System.out.println("闹钟发出滴答声");
}
}
修改之后,重新编译InterfaceTest.java并运行它,观察结果。
图八
(4)在第(3)小题中由于新加入的Clock类仅仅实现了Soundable接口的stopsound()和playsound()方法,而increaseVolume()和decreaseVolume()方法没有实现,因此它实质上是一个抽象类,而抽象类是不能实例化的,所以导致编译错误。
但是按照常理,闹钟的滴答声确实是不可以增大或减小的,那么如何解决这个问题呢?
现在请在Clock类中加入下面两个含{}空方法体的方法实现,再编译运行程序,看看会有什么变化。
publicvoidincreaseVolume(){}
publicvoiddecreaseVolume(){}
图九
(5)现在请模仿本实验的程序设计出一个自己的接口程序,要求先设计一个moveable可移动接口,然后分别设计3个类,即汽车Car、轮船Ship、飞机Aircraft来实现该接口,最后设计一个应用程序来使用它们。
程序代码:
importjava.util.*;
interfaceMoveable{
publicabstractvoidmove();
}
classCarimplementsMoveable{
publicvoidmove(){
System.out.println("汽车行驶");
}
}
classShipimplementsMoveable{
publicvoidmove(){
System.out.println("轮船航行");
}
}
classAircraftimplementsMoveable{
publicvoidmove(){
System.out.println("飞机飞行");
}
}
publicclassTestMoveable{
publicstaticvoidmain(String[]args){
Scannerinput=newScanner(System.in);
Moveable[]moveDevice=newMoveable[3];
moveDevice[0]=newCar();
moveDevice[1]=newShip();
moveDevice[2]=newAircraft();
System.out.println("您想乘坐什么?
请输入选择(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{
publicstaticvoidmain(String[]args){
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;
}
publicdoublegetArea(){
returnsuper.getArea()*length;
}
}
classTestCircle{
publicstaticvoidmain(String[]args){
Bb=newB(2,3);
System.out.println("半径为:
"+b.getRadius());
System.out.println("面积为:
"+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)
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 实验6 继承与接口 实验 继承 接口