Java实验(4):多态

多态

一、内容回顾

在Java中,一个引用类型变量可以指向多种不同类型的对象(包括父类型的引用可以指向子类型的对象,或者接口类型的引用可以指向实现该接口的类的实例)称为多态。多态作为面向对象编程的核心特征之一,能够有效提高程序的可扩展性。在这一部分将对多态涉及到的Java抽象类和接口技术进行分析介绍。

 

(一)抽象类

   用关键字 abstract 修饰的类叫做抽象类。

   抽象类有如下特点:

(1)含有抽象方法的类必须被声明为抽象类。

(2)抽象类必须被继承,抽象方法必须被重写。

(3)抽象类不能被实例化。

(4)抽象方法只需要声明,而不需要实现。

(5)如果某个类是抽象类,那么这个类既可以包含抽象方法,也可以包含具体的方法(有声明,有实现)。

   在Java中,与抽象类类似,接口是实现多态的关键技术。之前对接口进行了介绍,因此本次主要介绍接口与抽象类的差异。  

(二) 抽象类与接口的不同

(1)抽象类里可以有构造方法,而接口内不能有构造方法。

(2)抽象类中可以有普通成员变量,而接口中不能有普通成员变量。

(3)抽象类中可以包含非抽象的普通方法,而接口中所有的方法必须是抽象的,不能有非抽象的普通方法。

(4)抽象类中的抽象方法的访问类型可以是public ,protected和默认类型,但接口中的抽象方法只能是public类型的,并且默认即为public abstract类型。

(5)抽象类中可以包含静态方法,接口内不能包含静态方法。

(6)抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型不受限制,但接口中定义的变量只能是public static final类型,并且默认为public static final类型。

(7)一个类可以实现多个接口,但只能继承一个抽象类。

(8)接口更多的是在系统框架设计方面发挥作用,主要定义模块之间的通信,而抽象类主要在代码实现方面发挥作用,可以实现代码的重用

 

 

二、典型实例

例1   本例定义一个抽象类Shapes,并在类Shapes的两个子类Square和Circle中分别给出了getArea()和getPerimeter()的实现。

 

// AbstractClassTest.java

abstract class Shapes {

    public String getInfo(String shape) {

         return shape+" informations are:perimeter is "+getPerimeter()+",area is "+getArea();

    }

   abstract double getArea();

   abstract double getPerimeter();

}

class Circle extends Shapes {

    public double r;

    public double getArea() {

        return (r * r * Math.PI);

    }

    public double getPerimeter() {

        return (2 * Math.PI * r);

    }

    public Circle(int radius) {

        r = radius;

    }

}

class Square extends Shapes {

    public int width , height;

     public double getArea() {

        return (width * height);

    }

    public double getPerimeter() {

        return (2 * width + 2 * height);

    }

    public Square(int x, int y) {

        width = x;

        height = y;;

    }

}



public class AbstractClassTest{

    public static void main(String[] args) {

       Shapes shap1 = new Circle(4);

       Shapes shap2 = new Square(6,9);

       System.out.println(shap1.getInfo("circle"));

       System.out.println(shap2.getInfo("sqaure"));

    }

}

  

运行结果如图1所示。

图1 例1执行结果

 

例2  

// InterfaceTest.java

abstract class Duck{        

      FlyBehavior flyBehavior;

      QuackBehavior quackBehavior;

      public Duck(){}

      public abstract void display();

      public void swim(){

           System.out.println("All duck can swim!");

      }

      public void performFly(){

           flyBehavior.fly();  

      }

      public void performQuack(){

          quackBehavior.quack();

      }

 }

interface FlyBehavior{

     public void fly();    

 }

interface QuackBehavior{

     public void quack();

 }

class Quack implements QuackBehavior{

      public void quack(){

          System.out.println("Quack!");

      }

}



 class MuteQueak implements QuackBehavior{

      public void quack(){

          System.out.println("Silence!");

      }

}

 class FlyWithWings implements FlyBehavior{

      public void  fly(){

          System.out.println("I can fly!");

      }

 }

 class FlyNoWay implements FlyBehavior{

      public void  fly(){

          System.out.println("I can not fly!");

      }

 }  

class MallardDuck extends Duck{

      public MallardDuck (){      

          flyBehavior = new FlyWithWings ();

          quackBehavior = new Quack();

      }

      public void display(){

          System.out.println("I am MallardDuck!");

      }

}

class DecoyDuck extends Duck{

      public DecoyDuck() {      

          flyBehavior = new FlyNoWay ();

          quackBehavior = new MuteQueak();

       }

      public void display(){

           System.out.println("I am DecoyDuck!");

      }

 }

 public class  InterfaceTest{

       public static void main(String[] args) {

           Duck duck1 = new MallardDuck();

           Duck duck2 = new DecoyDuck();

           duck1.performQuack();

           duck1.performFly();

           duck1.display();

           duck2.performQuack();

           duck2.performFly();

           duck2.display();

}

}

  运行结果如图2所示。

说明:

①本例中的MallardDuck和DecoyDuck分别代表两种不同类型的鸭子。而FlyWithWings,FlyNoWay, Quack, MuteQueak这四个类分别通过实现FlyBehavior和QuackBehavior这两个接口来实现不同的“飞”和“叫”的动作。

②本例将“飞”和“叫”的动作用接口的方式实现的好处在于,其他类型的鸭子可以重复利用“飞,叫”的不同实现,从而达到代码复用的目的。另外,如果“飞”和“叫”的实现发生改变,则只需要修改实现FlyBehavior和QuackBehavior这两个接口的类,而不会将这种改变传递给不同类型的鸭子类,从而达到了代码易扩展,易维护的目的。

 

 

 图2 例2执行结果

 

三、实验设计

(一)实验一

    (1)实验目的

      让学生体验抽象类和多态的应用。

    (2)实验要求      设计3个类,分别是学生类Student,本科生类Undergaduate,研究生类Postgraduate,其中Student类是一个抽象类,它包含一些基本的学生信息,如姓名、所学课程、课程成绩等。Student类和主类代码如Student.java 和CourseGrade.java 所示。而Undergraduate类和Postgraduate都是Student类的子类,它们之间的主要差别是计算课程成绩等级的方法有所不同,研究生的标准要比本科生的标准高一些,如表1。所示假设某班级里既有本科生也有研究生,请编写程序统计出全班学生的成绩等级并显示出来。
 

表1   课程成绩等级表

本科生标准

研究生标准

80--100

优秀

90—100

优秀

70--80

良好

80—90

良好

60--70

一般

70—80

一般

50--60

及格

60—70

及格

50以下

不及格

60以下

不及格

// Student.java

abstract class Student {

    final static int CourseNo = 3;

    String type;//本科生或者研究生

    String name;//学生姓名

    int[] courses;//课程成绩数组

    String courseGrade;//成绩等级

    public Student(String name) {

       this.name = name;

       courses = new int[CourseNo];

courseGrade = null;

    }

    public abstract void calculateGrade();

    public String getType() {  

return type;

    }

    public void setType(String type) {

       this.type = type;

    }

    public String getName() {

       return name;

    }

    public void setName(String name) {

       this.name = name;

    }

    public int[] getCourses() {

       return courses;

    }

    public void setCourses(int[] courses) {

       this.courses = courses; 

    }

    public int getCourseScore(int courseNumber) {

       return courses[courseNumber];

    }

    public void setCourseScore(int courseNumber,int courseScore) {

       this.courses[courseNumber] = courseScore;

    }

    public String getCourseGrade() {

       return courseGrade;

    }

    public void setCourseGrade(String courseGrade) {

       this.courseGrade = courseGrade;

    }

}
// CourseGrade.java

public class CourseGrade {

     public static void main(String[] args) {

       Student[] students=new Student[5];

       students[0]=new Undergraduate("李明");

       students[1]=new Undergraduate("张红");

       students[2]=new Postgraduate("赵刚");

       students[3]=new Undergraduate("周伟");

       students[4]=new Postgraduate("刘凯");

       for(int i=0;i<5;i++){

           students[i].setCourseScore(0, 87);

           students[i].setCourseScore(1, 90);

           students[i].setCourseScore(2, 78);

       }

       for(int i=0;i<5;i++){

           students[i].calculateGrade();

       }

       System.out.println("姓名"+"   类型"+"   成绩");

       System.out.println("----------------------");

       for(int i=0;i<5;i++){

           System.out.println(students[i].getName()+"   "+

                  students[i].getType()+"   "+

                  students[i].getCourseGrade());

       }

    }

}

实验代码

//CouseGrade.java
abstract class Student{
	final static int CourseNo = 3;
	String type;//本科生或者研究生
	String name;//学生姓名
	int[] courses;//课程成绩数组
	String courseGrade;//成绩等级
	public Student(String name){
		this.name = name;
		courses = new int[CourseNo];
		courseGrade = null;
	}
	public abstract void calculateGrade();
	public String getType(){
		return type;
	}
	public void setType(String type){
		this.type = type;
	}
	public String getName(){
		return name;
	}
	public void setName(String name){
		this.name = name;
	}
	public int[] getCourses(){
		return courses;
	}
	public void setCourses(int[] courses){
		this.courses = courses;
	}
	public int getCourseScore(int courseNumber){
		return courses[courseNumber];
	}
	public void setCourseScore(int courseNumber,int courseScore){
		this.courses[courseNumber] = courseScore;
	}
	public String getCourseGrade(){
		return courseGrade;
	}
	public void setCourseGrade(String courseGrade){
		this.courseGrade = courseGrade;
	}
}

class Undergraduate extends Student{
	public Undergraduate(String name){ //类型和名字
		super(name);
		type = "本科生";
	}
	public void calculateGrade(){
		int total = 0;
		double average = 0;
		for(int i=0;i<CourseNo;i++){
			total += courses[i];
		}
		average = total/CourseNo; //计算各门成绩之和求平均值
		if(average>=80&&average<100) courseGrade = "优秀";
		else if(average>=70&&average<80) courseGrade = "良好";
		else if(average>=60&&average<70) courseGrade = "一般";
		else if(average>=50&&average<60) courseGrade = "及格";
		else courseGrade = "不及格";
	}
}

class Postgraduate extends Student{
	public Postgraduate(String name){
		super(name);
		type = "研究生";
	}
	public void calculateGrade(){
		int total = 0;
		double average = 0;
		for(int i=0;i<CourseNo;i++){
			total += courses[i];
		}
		average = total/CourseNo;//计算各门成绩之和再求平均值
		if(average>=90&&average<100) courseGrade = "优秀";
		else if(average>=80&&average<90) courseGrade = "良好";
		else if(average>=70&&average<80) courseGrade = "一般";
		else if(average>=60&&average<70) courseGrade = "及格";
		else courseGrade = "不及格";
	}
}
	


public class CourseGrade{
	public static void main(String[] args){
		Student[] students = new Student[5];
		students[0] = new Undergraduate("李明");
		students[1] = new Undergraduate("张红");
		students[2] = new Postgraduate("赵刚");
		students[3] = new Undergraduate("周伟");
		students[4] = new Postgraduate("刘凯");
		for(int i=0;i<5;i++){
			students[i].setCourseScore(0,87);
			students[i].setCourseScore(1,90);
			students[i].setCourseScore(2,78);
		}
		for(int i=0;i<5;i++){
		students[i].calculateGrade();
	}
	System.out.println("姓名"+"   类型"+"   成绩");
	System.out.println("----------------------");
	for(int i=0;i<5;i++){
		System.out.println(students[i].getName()+"  "+
			students[i].getType()+"  "+
			students[i].getCourseGrade());
		}
	}
}

运行结果


 

(3)实验效果展示

执行后的结果如图3所示。

图3 实验一效果展示

(4)实验指导

   本实验的关键是在子类(Undergraduate和Postgraduate)中实现calculateGrade()。实现的方式为将int[] courses中的成绩求和然后取平均值,最后根据表1来判断成绩等级。

 

(二)实验二

   (1)实验目的

      让学生体验抽象类和多态的应用。

   (2)实验要求

       如MainBoard.java和Assemblers.java所示,MainBoard为主板类,方法 usePCICard 用来启动和停止PCI插槽上的板卡。Assembler为主类,通过主板启动和停止网卡和声卡。要求以实现接口的形式实现网卡类和声卡类。 

// MainBoard.java

class  MainBoard {

    public void usePCICard(PCI p){

        p.start();

        p.stop();

   }

}
// Assemblers.java

public class Assembler{

     public static void main(String [] args){

        MainBoard mb=new MainBoard();

        NetworkCard nc=new NetworkCard();

        mb.usePCICard(nc);

        SoundCard sc=new SoundCard();

        mb.usePCICard(sc);

     }

}

实验代码

//Assembler.java
class MainBoard{
	public void usePCICard(PCI p){
		p.start();
		p.stop();
	}
}
interface PCI{ //声明一个PCI接口
	void start();
	void stop();
}

class NetworkCard implements PCI{ //网卡类实现接口
	public void start(){
		System.out.println("Send ...");
	}
	public void stop(){
		System.out.println("Network Stop.");
	}
}
class SoundCard implements PCI{ //声卡类实现接口
	public void start(){
		System.out.println("Du du...");
	}
	public void stop(){
		System.out.println("Sound Stop.");
	}
}
	
public class Assembler{
	public static void main(String[] args){
		MainBoard mb = new MainBoard();
		NetworkCard nc = new NetworkCard();
		mb.usePCICard(nc);
		SoundCard sc = new SoundCard();
		mb.usePCICard(sc);
	}
}

运行结果

 

(3)实验效果展示

执行后的结果如图4所示。

图4 实验二效果展示

 

(4)实验指导

     定义一个PCI接口,让网卡类和声卡类来实现这个接口。

 

 

  • 5
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我来为您展示一下 Java 实验代码实现多态、线程和文件读写的示例代码。 多态实现示例代码: ```java public class Shape { public void draw() { System.out.println("Drawing a shape"); } } public class Circle extends Shape { public void draw() { System.out.println("Drawing a circle"); } } public class Square extends Shape { public void draw() { System.out.println("Drawing a square"); } } public class Main { public static void main(String[] args) { Shape shape1 = new Circle(); Shape shape2 = new Square(); shape1.draw(); shape2.draw(); } } ``` 线程实现示例代码: ```java public class MyThread extends Thread { public void run() { for(int i = 1; i <= 5; i++) { System.out.println("Thread " + Thread.currentThread().getId() + ": " + i); } } } public class Main { public static void main(String[] args) { MyThread thread1 = new MyThread(); MyThread thread2 = new MyThread(); thread1.start(); thread2.start(); } } ``` 文件读写实现示例代码: ```java import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.Scanner; public class Main { public static void main(String[] args) { // 写入文件 try { FileWriter writer = new FileWriter("test.txt"); writer.write("Hello World!"); writer.close(); } catch (IOException e) { System.out.println("An error occurred."); e.printStackTrace(); } // 读取文件 try { File file = new File("test.txt"); Scanner scanner = new Scanner(file); while (scanner.hasNextLine()) { String data = scanner.nextLine(); System.out.println(data); } scanner.close(); } catch (IOException e) { System.out.println("An error occurred."); e.printStackTrace(); } } } ``` 以上就是 Java 实验代码实现多态、线程和文件读写的示例代码,希望能对您有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值