浙江大学城市学院实验报告课程名称:面向对象程序设计实验项目名称:类继承与接口(三)学生姓名专业:学号:实验地点:实验日期:年月日【实验目的】1.巩固Java类继承的相关知识2.理解对象上转型技术的优点和用途。
3.掌握接口的特点4.接口与抽象类的异同之处【实验内容】一、类继承相关知识强化1. 执行以下程序,给出执行Bbb的结果,并说明指出类Bbb的this.i与super.i的含义(即它们都对应哪个变量)。
class Aaa{int i;Aaa(int a){ i = a;}}class Bbb extends Aaa{int j,k;Bbb(int i){super(i);j = this.i;k = super.i;}public static void main(String[] args){Bbb b = new Bbb(18);System.out.println(b.j +"\t" + b.k);}}执行Bbb的结果:this.i与super.i的含义(即它们都对应哪个类中定义的变量):都对应Aaa类中的变量。
2.接着上面例子,将类Bbb改写为以下代码,请写出程序运行结果,并说明这个例子与上面例子的区别。
class Bbb extends Aaa{int i= -1,j= -1,k= -1; //比上面例子增加一个实例变量i;Bbb(int i){super(i);j = this.i; //本语句含义是:Bbb类中的变量i的值赋给jk = super.i; //本语句含义是:访问Aaa类中的变量i并将值赋给k}public static void main(String[] args){Bbb b = new Bbb(18);System.out.println(b.j +"\t" + b.k);}}执行Bbb的结果:-1 18这个例子与上面例子的区别:在Bbb类中也定义了变量i,将Bbb的直接超类Aaa中的变量i给覆盖掉了。
3.对以下程序,给出执行Bbb的结果,并分析Bbb中main方法中a.show(1), b.show(1),c.show(1)的结果。
class Aaa{void show(){System.out.println("Aaa中定义的show()");}void show(int i){System.out.println("Aaa中定义的show(int i)");}}class Bbb extends Aaa{void show(){System.out.println("Bbb中定义的show()");}Aaa a = new Aaa();Bbb b = new Bbb();Aaa c = new Bbb();a.show(1);b.show(1);c.show(1);}}执行Bbb的结果:上面a.show(1)执行了那个类中定义的方法: Aaa类上面b.show(1);执行了那个类中定义的方法: Aaa类上面c.show(1)执行了那个类中定义的方法: Aaa类分析:类Bbb中的方法覆盖的的是类Aaa中的void show()方法,并未覆盖void show(int i),而 a.show(1);b.show(1);c.show(1);都是执行了Aaa类中的void show(int i)方法。
a.show(1)是直接访问超类Aaa中的void show(int i)方法,b.show(1)是子类Bbb继承了类Aaa中的void show(int i)方法,从而执行,c.show(1)中c是上转型对象,子类对象的引用向上转型为超类类型,从而执行void show(int i)方法。
4. 对以下程序,给出执行Bbb的结果,并分析这个例子结果与前面第4个例子,你可以得出什么结论。
class Aaa{int i = 10;static void show(){System.out.println("Aaa中定义的show()");}}class Bbb extends Aaa{int i = 20;static void show(){System.out.println("Bbb中定义的show()");}Aaa a = new Aaa();Bbb b = new Bbb();Aaa c = new Bbb();a.show();b.show();c.show();((Bbb)c).show();System.out.println(c.i); //考虑此处System.out.println(((Bbb)c).i); //考虑此处}}执行Bbb的结果:((Bbb)c).show()执行结果: Bbb中定义的show()System.out.println(c.i)执行结果: 10System.out.println(((Bbb)c).i)执行结果: 20分析与结论:A aa c = new Bbb();中c为上转型对象,将子类对象的引用转为超类类型,c本是子类Bbb 的对象,但通过向上转型,c.i引用的是超类的变量,同时也可以通过(Bbb)c)的方式将c强制向下转型,则( (Bbb)c).i访问的是子类Bbb的成员变量。
二、程序分析思考以下是例5.22的部分关键代码,请分析思考以下问题:(1)Student类中设计抽象方法cost会带来什么好处?(2)Student类的compareCost方法可以用于比较哪些类型的对象?如果没有设计抽象方法cost,那么会发生什么问题?注意:分析重点是软件设计的通用性考虑。
abstract class Student {//定义学生对象的抽象超类private String name;public Student(String name){ = name; }public abstract double cost();//声明抽象方法,表示学习费用public double compareCost(Student otherStudent){//当前对象与参数对象的费用比较return this.cost() - otherStudent.cost(); //返回大于、等于、小于零的数字}public String getName(){return ; }public void setName(String name){ = name; }}class StudentCostTool{static double sumCost(Student[] students){//计算students所有学生的费用之和double sum = 0;for(int i=0;i<students.length;i++)sum = sum + students[i].cost();return sum;}static double averageCost(Student[] students){//计算students学生的平均费用return sumCost(students)/students.length;}static double maxCost(Student[] students){//计算students所有学生的费用最大值if(students.length == 1)return students[0].cost();int index = 0;for(int i=0;i<students.length;i++)if(students[index].compareCost(students[i]) < 0)index = i;return students[index].cost();}}(1)Student类中设计抽象方法cost会带来什么好处?答:由于不同的学生费用不同,无法做到学费的统一通用,因此设计抽象方法cost,那么就可以在不同学生类中调用抽象方法cost在其中用不同的代码返回相应学生的学费。
(2)Student类的compareCost方法可以用于比较哪些类型的对象?如果没有设计抽象方法cost,那么会发生什么问题?答:用于比较哪些类型的对象当前对象,上转型对象及其子类对象。
如果没有设计抽象方法cost,那么compareCost方法就只能在Student的子类中设计了,即每个子类都编写一个compareCost方法,这样做就会导致相同代码的多处重复。
三、接口与抽象类实验1. 编译下面的程序, 指出错误.interface A{ //语句1void show();void show(int i){System.out.println("A show()");}}(1) 是否出错? 出错原因?是,接口A中必须为抽象方法,不能定义非抽象方法,而上面的void show(int i)为非抽象方法,应该为“void show(int i);”,不能有实现代码。
(2) 如果将上面语句1的interface改为abstract class , 编译是否出错?(提示: 注意abstract修饰符)出错。
当interface改为abstract class时,说明A为抽象类,那么抽象类A中的抽象方法void show();应该在前面加上abstract修饰符。
(3)根据上面的(1)和(2), 可以看出接口与抽象类的什么区别?接口中只能声明抽象方法,而抽象类中既能声明抽象方法,又能声明非抽象方法,但是抽象类中的抽象方法前面必须加上abstract修饰符,而接口则不需要,因为它被默认为抽象方法。
2. 编译下面的程序, 指出错误.interface IA{void show();void show(int i);}class A implements IA{ //语句1public void show(int i){ //语句2System.out.println("A show()");}}(1) 上面的程序编译是否出错? 出错原因?是,A是接口IA的实现类,它继承了接口IA的所有成员,但类A中只实现了接口IA中的无参抽象方法show,但还有一个有参的抽象方法show没有实现,所以必须将类A声明为抽象类,即在class A前面加上修饰符abstract。
(2) 如果将语句1中的class 改为abstract class, 编译是否出错? 为何?不出错。
A是接口IA的实现类,它继承了接口IA的所有成员,但类A中只实现了接口IA 中的无参抽象方法show,但还有一个有参的抽象方法show没有实现,所以必须将类A声明为抽象类,即在class A前面加上修饰符abstract。