实验 6——继承与接口

[实验目的]

1、掌握java 继承中父类及其子类的定义方法。

2、掌握子类重写父类同名方法的方法。

3、掌握接口的用法。

(1) 学习如何定义接口 ;

(2) 掌握接口的实现方式 ;

(3) 使用实现了接口的类 ;

    (4) 理解接口与抽象类的区别。

[实验要求]

  1. 复习理论教学中所学的内容。
  2. 认真进行实验预习,查阅参考书,书写源程序,书写实验预习报告。
  3. 认真总结实验并书写实验报告。

 [实验内容]

  1. 类的继承性练习

(1) 程序源代码如下。

  public class Student

  {

   protected String xm; //姓名,具有保护修饰符的成员变量

   protected int xh;//学号

   void setdata(String xm,int xh) //设置数据的方法

   {

    this.xm=xm;

        this.xh=xh;

   }

   public void print() //输出数据的方法

   {

    System.out.println(xm+", "+xh);

   }

  }

(二)创建将被继承的类

(1) 程序功能:通过Student类产生子类CollegeStudent,其不仅具有父类的成员变量xm(姓名)、xh(学号),还定义了新成员变量xy(学院)、bj(bj)。在程序中调用了父类的print 方法,同时可以看出子类也具有该方法。

package project6;

public class CollegeStudent extends Student{
	public static void main(String[] args) {
		CollegeStudent c=new CollegeStudent();
		c.setdata("李华", 1,"计科","大数据二班");
		c.print();
	}
	private String xy;
	private String bj;
	
	void setdata(String xm,int xh,String xy,String bj) {
		super.setdata(xm, xh);
		this.xy=xy;
		this.bj=bj;
	}
	public void print() {
		super.print();
		System.out.println(xy+" "+bj);
	}
}

(三)了解成员方法的覆盖方式

编写覆盖了Object 类toString方法的一个类,并用System.out.println()输出该类的一个对象

package project6;

public class ToString {

	private String s;
	public static void main(String[] args) {
		ToString t=new ToString("李华");
		System.out.println(t.toString());

	}
	
	public ToString() {
	}
	public ToString(String s) {
		this.s=s;
	}
@Override
	public String toString() {
		return "我的名字是"+s;
	}
}

试着以Point类为例,尝试为Object类的clone()和equals()方法进行覆盖,Point类包含私有成员x,y,构造方法1(包含两个参数a,b),构造方法2(参数为Point p),clone方法,equals方法,toString方法。用TestPoint类进行测试

ackage project6;

public class TestPoint {

	public static void main(String[] args) throws CloneNotSupportedException {
		Point p1=new Point(1,1);
		Point p2;
		Point p3=new Point(2,2);
		Point p4=new Point(p3);
		p2=(Point)p1.clone();
		System.out.println("p1:"+p1.toString());
		if(p2==null) 
			System.out.println("p2==null");
		else
		    System.out.println("p2:"+p2.toString());
		System.out.println("p3:"+p3.toString());
		System.out.println("p4:"+p4.toString());
		System.out.println("p1与p2相等吗?"+p1.equals(p2));
		System.out.println("p1与p3相等吗?"+p1.equals(p3));
		System.out.println("p3与p4相等吗?"+p3.equals(p4));
	}

}
class Point{
	private int x;
	private int y;
	
	public Point(int a,int b) {
		x=a;
		y=b;
	}
    public Point(Point p) {
    	this.x=p.x;
    	this.y=p.y;
	}
    @Override
    public Object clone() throws CloneNotSupportedException{
    		Point p=new Point(this.x,this.y);
    		return p;
    }
    @Override
    public boolean equals(Object o) {
    	if(o instanceof Point) { 
    		if((x==((Point)o).x)&&(y==((Point)o).y))
    		    return true;
    		else
    			return false;
    	}
    	else
    		return false;
    }
   @Override 
    public String toString() {
    	return "x="+x+","+"y="+y;
    }
}

(四)this、super和super()的使用

程序功能:程序功能:说明this、super 和super()的用法。程序首先定义Point(点)类,然后创建点的子类Line(线)。最后通过TestLine类输出线段的长度。程序中通过super(a,b)调用父类Point 的构造方法为父类的x 和y 赋值。在子类Line 的setLine方法中,因为参数名和成员变量名相同,为给成员变量赋值,使用this 引用,告诉编译器是为当前类的成员变量赋值。在length 和toString 方法中使用父类成员变量时,使用super 引用,告诉编译器使用的是父类的成员变量。

package project6_1;
public class TestLine {

	public static void main(String[] args) {
		Line l=new Line(10,10);
		l.setLine(new Point(6,7));
		System.out.println("l的信息为:"+l.toString());
		System.out.println("l的长度为:"+l.length());
	}
}

class Point{
	private int x;
	private int y;
	
	public Point(int a,int b) {
		x=a;
		y=b;
	}
    public Point(Point p) {
    	this.x=p.x;
    	this.y=p.y;
	}
    
    public int getX() {
    	return x;
    }
    public int getY() {
    	return y;
    }
}

class Line extends Point{
	private Point p;

	public Line(int a, int b) {
		super(a, b);
	}
	public void setLine(Point p) {
		this.p=p;
	}
	public double length() {
		double len=Math.sqrt((super.getX()-p.getX())*(super.getX()-p.getX())+(super.getY()-p.getY())*(super.getY()-p.getY()));
	    return len;
	}
	@Override
	public String toString() {
		return "父类的点为:("+super.getX()+","+super.getY()+")"+"  ,子类的点为:("+p.getX()+","+p.getY()+")";
	}
}

(五)  接口的实现与运用

实验任务 :

本实验的任务是设计和实现一个 Soundable 接口 , 该接口具有发声功能 , 同时还能够调节声音大小。 Soundable 接口的这些功能将会由 3 种声音设备来具体实现 , 它们分别是收音机 Radio 、随身昕 Walkman 和手机 Mobilephone 。最后还要设计一个应用程序类来使用这些实现了 Soundable 接口的声音设备类。程序运行时 , 先询问用户想听哪种设备 , 然后程序就会按照该设备的工作方式来发出声音。

实验步骤 :

(1) 仔细阅读程序, 并完成其中的代码1~代码3。

// InterfaceTest.java

import java.util.Scanner;

interface Soundable { 

    public void increaseVolume( );

    public void decreaseVolume( );

    public void stopSound( );

    public void playSound( );

}

class Radio implements Soundable {

  public void increaseVolume( ) {

     System.out.println("增大收音机音量");

  } 

  public void decreaseVolume( ) {

     System.out.println("减小收音机音量");

  }

  public void stopSound( ) {

     System.out.println("关闭收音机");

  }

  public void playSound( ) {

     System.out.println("收音机播放广播");

  }

}

class Walkman implements Soundable {

  public void increaseVolume( ) {

     System.out.println("增大随声听音量");

  } 

  public void decreaseVolume( ) {

     代码1 System.out.println("减小随声听音量"); //代码1// 输出减小随声听音量

  }

  public void stopSound( ) {

     System.out.println("关闭随声听");

  }

  public void playSound( ) {

     System.out.println("随声听发出音乐");

  }

}

class Mobilephone implements Soundable {

  public void increaseVolume( ) {

     System.out.println("增大手机音量");

  } 

  public void decreaseVolume( ) {

     System.out.println("减小手机音量");

  }

  public void stopSound( ) {

     System.out.println("关闭手机");

  }

  public void playSound( ) {

     System.out.println("手机发出来电铃声");

  }

}

class People {

   private String name;

   private int    age;  

   public void listen(Soundable s) {    

      s.playSound( );

   }

}

public class InterfaceTest {

   public static void main(String[] args) {      

      int i;     

      People sportsman = new People( );

       Scanner scanner = new Scanner(System.in);

      Soundable[] soundDevice = new Soundable[3];

       //往声音设备数组中放入能发声的设备

      soundDevice[0] = new Radio( );

      soundDevice[1] = new Walkman( );

      soundDevice[2]=new Mobilephone(); //代码2//创建手机对象并赋值给soundDevice[2]

      System.out.println("你想听什么? 请输入选择:0-收音机 1-随声听 2-手机");

       i = scanner.nextInt( );      

      //开始听声音

      sportsman.listen(soundDevice[i]);

      soundDevice[i].increaseVolume( );

      代码3 soundDevice[i].stopSound(); //代码3//调用stopSound( )方法

   }

}

(2) 打开文本编辑器编辑 InterfaceTest.java 并保存 , 然后在Eclipse 环境中进行编译 , 编译的结果将会产生 6 个 class 文件 , 其中包括 Soundable.class, 虽然 Soundable 本身是一个接口 , 但编译之后也会产生 class 文件。

    (3) 编译之后运行这个程序 , 观察所得结果。

思考

    (1) 请问在 InterfaceTest 类中 ,SoundDevice[] 数组是什么类型的 , 该数组为什么能存放 3 种不同的对象 Radio、Walkman 和 Mobilephone 呢 ?

答  

SoundDevice[] 数组是接口类型。

Radio、Walkman 和 Mobilephone三个类都继承了接口Soundable,接口Soundable是那三个类的父亲,父类的引用可以指向任意一个子类的对象,所以该数组为什么能存放 3 种不同的对象 Radio、Walkman 和 Mobilephone。

    (2) 在程序中 ,Soundable 是一个接口 , 那么该接口是否可以被实例化呢 ? 请在InterfaceTest 类的 main() 方法中加入以下语句试验一下 , 并分析结果。

Soundable    Sound=new Soundable(),

结果出现错误:

原因是Soundable 是一个接口,类似抽象类,只能声明引用,不能用new操作符给对象实例化。

    (3) 现在假定要为程序增加一个闹钟类 Clock, 该类也实现 Soundable 接口 , 能够发出滴答声 , 请将以下的 Clock 类加入到 InterfaceTest.java 程序中 , 并在 InterfaceTest 类的 main() 方法中加入 SoundDevice[3] new Clock(); 语句。

class Clock implements Soundable{

   public void Stopsound(){

   System.out.println(" 关闭闹钟 ");

}

public void Playsound(){

   system.out.println(" 闹钟发出滴答声 ");

   }

}

修改之后 , 重新编译 InterfaceTest.java 并运行它 , 观察结果。

报错:

Exception in thread "main" java.lang.AbstractMethodError: Receiver class project6.Clock does not define or inherit an implementation of the resolved method 'abstract void increaseVolume()' of interface project6.Soundable.

原因应该是increaseVolume() decreaseVolume() 方法没有实现。

(4) 在第 (3) 小题中由于新加入的 Clock 类仅仅实现了 Soundable 接口的stopsound() 和 playsound() 方法 , 而 increaseVolume() 和 decreaseVolume() 方法没有实现 , 因此它实质上是一个抽象类 , 而抽象类是不能实例化的 , 所以导致编译错误。但是按照常理 , 闹钟的滴答声确实是不可以增大或减小的 , 那么如何解决这个问题呢 ? 现在请在 Clock 类中加入下面两个含 {} 空方法体的方法实现 , 再编译运行程序 , 看看会有什么变化。

public void increaseVolume(){}

public void decreaseVolume(){}

成功运行,没有报错:

(5) 现在请模仿本实验的程序设计出一个自己的接口程序 , 要求先设计一个 moveable 可移动接口 , 然后分别设计 3 个类 , 即汽车 Car 、轮船 Ship 、飞机 Aircraft 来实现该接口 , 最后设计一个应用程序来使用它们。

package project6;
import java.util.*;
interface moveable{
	public void startmove();
	public void stopmove();
	public void increasespeed();
	public void decreasespeed();
}
class Car implements moveable{
	public void startmove() {
		System.out.println("汽车跑");
	}
	public void stopmove() {
		System.out.println("汽车停");
	}
	public void increasespeed() {
		System.out.println("汽车加速");
	}
	public void decreasespeed() {
		System.out.println("汽车减速");
	}
}
class Ship implements moveable{
	public void startmove() {
		System.out.println("船跑");
	}
	public void stopmove() {
		System.out.println("船停");
	}
	public void increasespeed() {
		System.out.println("船加速");
	}
	public void decreasespeed() {
		System.out.println("船减速");
	}
}
class Aircraft implements moveable{
	public void startmove() {
		System.out.println("飞机飞");
	}
	public void stopmove() {
		System.out.println("飞机停");
	}
	public void increasespeed() {
		System.out.println("飞机加速");
	}
	public void decreasespeed() {
		System.out.println("飞机减速");
	}
}
public class MoveableTest {

	public static void main(String[] args) {
		Scanner input=new Scanner(System.in);
		moveable[] move=new moveable[3];
		move[0]=new Car();
		move[1]=new Ship();
		move[2]=new Aircraft();
		System.out.println("选择一种交通工具:0-汽车 1-船 2-飞机");
		int i=input.nextInt();
		show(move[i]);
	}

	public static void show(moveable m) {
		m.startmove();
		m.increasespeed();
		m.decreasespeed();
		m.decreasespeed();
	}
}

(六)深复制(掌握Clonable接口的使用)

重写书中的程序清单10-6的Course类,增加一个clone方法,执行students域的深度复制。

package project6;

public class TestCourse {
  public static void main(String[] args) {
    Course course1 = new Course("Data Structures");
    Course course2 = new Course("Database Systems");
    Course course3;//重新定义一个Course对象

    course1.addStudent("Peter Jones");
    course1.addStudent("Brian Smith");
    course1.addStudent("Anne Kennedy");
    
    course2.addStudent("Peter Jones");
    course2.addStudent("Steve Smith");
    course2.dropStudent("Peter Jones");//删除course2里的学生Peter Jones
    course3=(Course) course1.clone();//将course1复制到course3
    
    System.out.println("Number of students in course1: "
      + course1.getNumberOfStudents());
    String[] students1 = course1.getStudents();
    for (int i = 0; i < course1.getNumberOfStudents(); i++)
      System.out.print(students1[i] + ", ");
    
    System.out.println();
    System.out.println("Number of students in course2: "
      + course2.getNumberOfStudents());
    String[] students2 = course2.getStudents();
    for (int i = 0; i < course2.getNumberOfStudents(); i++)
        System.out.print(students2[i] + ", ");
    System.out.println();
    System.out.println("除了删除了一个学生,以上其余的为书中原有输出");
    //除了删除了一个学生,其余为书中原有输出
    
    //修改course3的学生姓名前输出一次
    System.out.println();
    System.out.println("以下为本实验重新加入的输出:");
    System.out.println("修改crouse3前:");
    System.out.println("Number of students in course3: "
    	      + course3.getNumberOfStudents());
    String[] students3 = course3.getStudents();
    for (int i = 0; i < course3.getNumberOfStudents(); i++)
        System.out.print(students3[i] + ", ");
    
  //修改course3的学生姓名后输出一次
    students3[1]="Li Hua";
    System.out.println();
    System.out.println("修改crouse3后:");
    System.out.println("Number of students in course3: "
    	      + course3.getNumberOfStudents());
    for (int i = 0; i < course3.getNumberOfStudents(); i++)
        System.out.print(students3[i] + ", ");
//    System.out.println(course1);
//    System.out.println(course3);
  }
}
class Course implements Cloneable{
	  private String courseName;
	  private String[] students = new String[100];
	  private int numberOfStudents;
	    
	  public Course(String courseName) {
	    this.courseName = courseName;
	  }
	  
	  public void addStudent(String student) {
	    students[numberOfStudents] = student;
	    numberOfStudents++;
	  }
	  
	  public String[] getStudents() {
	    return students;
	  }

	  public int getNumberOfStudents() {
	    return numberOfStudents;
	  }  

	  public String getCourseName() {
	    return courseName;
	  }  
	  //删除学生
	  public void dropStudent(String student) {
	    for(int i=0;i<numberOfStudents;i++) {
	    	if(students[i]==student) {
	    		for(int j=i;j<numberOfStudents;j++) {
	    			students[j]=students[j+1];
	    		}
	    		numberOfStudents--;
	    	}
	    	break;
	    }
	  }
	  @Override//重写clone()函数
	  public Object clone() {
		  try {
			  Course c=(Course)super.clone();
			  String[] cs=new String[numberOfStudents];
			  //cs=this.students.clone();
			  for(int i=0;i<numberOfStudents;i++) {
				  c.students[i]=this.students[i];
			  }
			  return c;
		  }
		  catch(CloneNotSupportedException ex) {
			  return null;
		  }
	  }
	}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值