Java实验5《面向对象——多态》

一、实验目的

  1. 理解多态性和动态绑定
  2. 存储、提取和操作ArrayList中的对象

二、实验内容

  1. 【Person、Student、Employee类】(注:此题在书上原题基础上有修改)设计一个名为Person的类和它的两个名为Student和Employee子类。
      每个人都有姓名和电话号码。学生有年级状态(大一、大二、大三或大四)。将这些状态定义为常量。一个雇员有工资和受聘日期。定义一个名为MyDate的类,包含数据域:year(年)、month(月)和day(日)。将各个类的数据域进行封装,并设置合理的读写访问器。
    覆盖每个类中的toString方法,返回类名及相应的类中可以获取的所有信息构成的字符串,如Person类的toString方法返回“Person类:姓名为*** 电话为***”;Student类的toString方法返回“Student类: 姓名为*** 电话为*** 年级为***”。
      在Student和Employee两个类中分别加入displayObject()方法,可以打印出对学生和雇员的提示消息,提示学生“to ***(学生姓名):请按时交实验报告”,提示雇员“to ***(雇员姓名):请按时上班”。
      目标输出任务:
  • 画出这些类的UML图。
  • 实现这些类。
  • 编写一个测试类,
    1)创建方法public static void m1(Person p),显示p的姓名;
    2)创建方法public static void m2(Person p),打印p的toString方法返回的字符串;
    3)创建方法public static void m3(Person p),如果p是Student类或者Employee类的实例,分别调用它们的displayObject();
    4)在主函数中创建Person、Student、Employee的对象实例,将它们均声明为Person类对象。将它们分别传入m1、m2和m3,体会多态。

 1.1 UML图
Java实验5《面向对象——多态》_第1张图片

 1.2 程序代码:
(1)TestProgram1类的源程序:

//TestProgram1类的源程序
//此测试类用于测试Person类、Student类、Employee类
public class TestProgram1{
     public static void main(String[] args){
     //在主函数中创建Person、Student、Employee的对象实例,
  //将它们均声明为Person类对象。将它们分别传入m1、m2和m3
           Person p1 = new Person("Annay", "15269358569");
           Person p2 = new Student("大一", "Boens", "14985685962");
           Person p3 = new Employee("10万/月", new MyDate("2018", "1", "20") , "Concy", "18659856589");
           
           //将对象p1分别传入方法m1、m2、m3中
           m1(p1);
           m2(p1);
           m3(p1);
           //将对象p2分别传入方法m1、m2、m3中
           m1(p2);
           m2(p2);
           m3(p2);

           //将对象p3分别传入方法m1、m2、m3中
           m1(p3);
           m2(p3);
           m3(p3);
         
     }//mian方法结束

     //显示p的姓名
     public static void m1(Person p){
           System.out.println( p.getName() );
     }//m1结束

     //打印p的toString方法返回的字符串
     public static void m2(Person p){
          System.out.println( p.toString() );
     }//m2结束

      //如果p是Student类或者Employee类的实例,分别调用它们//的displayObject()
     public static void m3(Person p){
           if(p instanceof Student)
                 ((Student)p).displayObject();
           else if(p instanceof Employee)
                 ((Employee)p).displayObject();
     }//m3结束
}//TestClass结束

(2)Person类的源程序:

//Person类的源程序
public class Person {
    private String name;
    private String numbers;

    public Person(){

    }
   
    public Person(String name, String numbers){
         this.name = name;
         this.numbers = numbers;
    }

    public String getName(){
         return name;
    }

    public String getNumbers(){
           return numbers;
    }

    public void setName(String name){
          this.name = name;
    }

    public void setNumbers(String numbers){
            this.numbers = numbers;
    }
    
    public String toString(){
          return "Person类:姓名为" + name + "  电话为" + numbers;
    }
}

(3)Student类的源程序:

//Student类的源程序
public class Student extends Person{
     private String status;

     public Student(){

     }

     public Student(String status, String name, String numbers){
          super(name, numbers);
          this.status = status;
     }

     public String getStatus(){
          return status;
     }
 
     public void setStatus(String status){
          this.status = status;
     }

     public void displayObject(){
         System.out.println("to " + super.getName() + ":请按时交实验报告");
     }
     
    public String toString(){
        return "Student类:姓名为" + super.getName() + "  电话为" 
                + super.getNumbers() + "  年级为" + status;
    }
}

(4)Employee类的源程序:

//Employee类的源程序
public class Employee extends Person {
    private String salary;
    private MyDate dateOfEmployment=new MyDate();

    public Employee(){
    	
    }

    public Employee(String salary,MyDate dateOfEmployment,String name,String numbers){
    	super(name,numbers);
    	this.salary = salary;
    	this.dateOfEmployment = dateOfEmployment;
    }

    public String getSalary(){
    	return salary;
    }

    public void setSalary(String salary){
        this.salary = salary;
    }

    public MyDate getDateOfEmployment(){
    	return dateOfEmployment;
    }

    public void setDateOfEmployment(MyDate dateOfEmployment){
        this.dateOfEmployment = dateOfEmployment;
     }

    public void displayObject(){
    	System.out.println("to "+ super.getName() + ": 请按时上班");
    }

    public String toString(){
         return "Employee类:姓名为" + super.getName() 
+ "  电话为" + super.getNumbers() + "  工资为" + salary;
   }
}

(5)MyDate类的源程序:

//MyDate类的源程序:
public class MyDate{
	private String year;
	private String month;
	private String day;
        
        public MyDate(){
            
        }

        public MyDate(String year, String month, String day){
             this.year = year;
             this.month = month;
             this.day = day;
        } 

        public String getYear(){
             return year;
        }

        public String getMonth(){
             return month;
        }

        public String getDay(){
               return day;
         }

        public void setYear(){
              this.year = year;
        }

        public void setMonth(String month){
            this.month = month;
        }

        public void setDay(String day){
           this.day = day;       
        }
}

  1.3 运行结果与分析:
Java实验5《面向对象——多态》_第2张图片
    运行正确,符合题目要求。创建三个类的实例,三个测试方法,每个实例都用三个方法测试。

  1.4 心得体会:
    此题主要是三个类之间的继承与多态关系应用,先画UML图再一次性写出三个类,当然还有额外的MyDate类,最后再写测试类,测试类中的方法调用需谨慎书写。这道题的难点在于不同类之间的方法与对象的调用,类的声明类型与实际类型的应用。


  1. (P380, 11.5)【课程类Course】改写程序清单10-6中的Course类。 使用ArrayList代替数组来存储学生。不应该改变Course类的原始合约 (即不要改变构造方法和方法的方法头定义,包括返回类型、方法名及参数列表,但私有的成员可以改变)。
//程序清单10-6
public class Course {
  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) {
    // Left as an exercise in Exercise 9.9
  }
}
//程序清单10-5
//【注意:请参考以下程序来测试Course类,同时注意在此段程序基础上,增加必要的代码,以完整地测试Course类中定义的所有方法】
public class TestCourse {
  public static void main(String[] args) {
    Course course1 = new Course("Data Structures");
    Course course2 = new Course("Database Systems");

    course1.addStudent("Peter Jones");
    course1.addStudent("Brian Smith");
    course1.addStudent("Anne Kennedy");

    course2.addStudent("Peter Jones");
    course2.addStudent("Steve Smith");

    System.out.println("Number of students in course1: "
      + course1.getNumberOfStudents());
    String[] students = course1.getStudents();
    for (int i = 0; i < course1.getNumberOfStudents(); i++)
      System.out.print(students[i] + ", ");
    
    System.out.println();
    System.out.print("Number of students in course2: "
      + course2.getNumberOfStudents());
  }
}

 2.1 程序代码:
(1)Course类

//Course类
import java.util.ArrayList;

public class Course {
  private String courseName;
  private ArrayList<String> students = new ArrayList<>();
    
  public Course(String courseName) {
    this.courseName = courseName;
  }
  
  //添加学生
  public void addStudent(String student) {
    students.add(student);
  }
  
  //输出学生姓名
  public String[] getStudents() {
    int size = students.size();
    String[] st = new String[size];
    for(int i=0; i<students.size(); i++)
         st[i] = students.get(i);
    return st;
  }

  //返回数组大小
  public int getNumberOfStudents() {
    return students.size();
  }  

  //返回课程名称
  public String getCourseName() {
    return courseName;
  }  
  
  //删除学生
  public void dropStudent(String student) {
    students.remove(student);
  }
}

(2)TestCourse类

//TestCourse类
public class TestCourse {
  public static void main(String[] args) {
    Course course1 = new Course("Data Structures");
    Course course2 = new Course("Database Systems");

    //输入coures1,course2的学生名字
    course1.addStudent("Peter Jones");
    course1.addStudent("Brian Smith");
    course1.addStudent("Anne Kennedy");

    course2.addStudent("Peter Jones");
    course2.addStudent("Steve Smith");

    //输出course1的名称
	System.out.println("course1: " + course1.getCourseName());

    //输出course1的学生数量
    System.out.println("Number of students in course1: "
      + course1.getNumberOfStudents());

    //输出course1的学生名字
    String[] st1 = course1.getStudents();
    for (int i = 0; i < course1.getNumberOfStudents(); i++)
      System.out.print(st1[i] + ", ");
    
    System.out.println();
    System.out.println();

    System.out.println("After coures1 removes \"Peter Jones\" ");
    //删除courese1中的“Peter Jones”
    course1.dropStudent("Peter Jones");

    //输出删除后course1的学生数量
    System.out.println("Number of students in course1: "
      + course1.getNumberOfStudents());

    //输出删除后course1的学生名字
    String[] st3 = course1.getStudents();
    for (int i = 0; i < course1.getNumberOfStudents(); i++)
      System.out.print(st3[i] + ", ");

    System.out.println();
    System.out.println();

    //输出course2的名称
    System.out.println("course2: " + course2.getCourseName());

    //输出course2的学生数量    
    System.out.println("Number of students in course2: "
      + course2.getNumberOfStudents());

    //输出course2的学生名字
    String[] st2 = course2.getStudents();
    for (int i = 0; i < course2.getNumberOfStudents(); i++)
      System.out.print(st2[i] + ", ");

    System.out.println();
    System.out.println();
 
    System.out.println("After coures2 removes \"Steve Smith\" ");

    //删除courese2中的“Steve Smith”
    course2.dropStudent("Steve Smith");

    //输出删除后course2的学生数量
    System.out.println("Number of students in course2: "
      + course2.getNumberOfStudents());

    //输出删除后course2的学生名字
    String[] st4 = course2.getStudents();
    for (int i = 0; i < course2.getNumberOfStudents(); i++)
      System.out.print(st4[i] + ", ");

    System.out.println();
  }
}

  2.2 运行结果:
Java实验5《面向对象——多态》_第3张图片

  2.3 心得体会:
    此题主要是ArrayList类中的方法的调用与运用,再就是测试时运用所有已创建的方法以及调整输出格式。


  1. 附加题(可选做)(P381, 11.10)(利用继承实现MyStack)在程序清单11-10中,MyStack是用组合实现的。扩展ArrayList创建一个新的栈类。实现MyStack类。编写一个测试程序,提示用户输入5个字符串,然后以逆序显示这些字符串。

  3.1 程序代码:

import java.util.Scanner;   
public class MyStack extends java.util.ArrayList{
      public MyStack(){

      }

      //实现获取栈的最后一个元素
      public Object peek(){
           return this.get(this.size()-1);
      }
     
      //创建栈的实例并把栈的最后一个元素传给实例对象,然后删除这个元素
      public Object pop(){
          Object o = this.get(this.size()-1);
          this.remove(this.size() - 1);
          return o;
      }

     //将这个实例对象放入一个新的栈中
     public void push(Object o){
        this.add(o);
     }
     
     //测试程序
     @SuppressWarnings("unchecked")
     public static void main(String[] args){
        Scanner input = new Scanner(System.in);

        System.out.println("请输入5个字符串:  ");
        MyStack mystack = new MyStack();
        for(int i = 0; i < 5; i++) {
           String st = input.next();
           mystack.push(st);
        }

        System.out.println("逆序输出为: ");
        for(int i=0; i<5; i++)
            System.out.print(mystack.pop() + " ");

        System.out.println();
        }//main方法结束

}//MyStack类结束

  3.2 运行结果及分析:
Java实验5《面向对象——多态》_第4张图片
  运行结果正确,输入5个字符串,利用MyStack逆序输出,但是编译时出现了一个小问题,不过不影响运行,具体说明见下。

  3.3 心得体会:
  本题利用继承关系,创建MyStack继承类,关键在于思路。想清楚继承类中需要书写的方法,其实就三个,取栈的最后一个元素、取栈的最后一个元素再删除、向栈里面添加元素。再就是这三个方法的书写,直接使用泛型,调用时采用类似this.get()的方式调用就好。
  本题遗留了一个小问题:
Alt
  程序编译显示以上错误,后经过检查是使用泛型时需要确定类型的问题,其中一种解决方法是添加注释:@SuppressWarnings(“unchecked”)
  但是,貌似由于版本问题,问题依旧存在。
  还有一个解决方法是泛型具体化,不过此方法在本题中不方便使用,所以问题暂未解决。


你可能感兴趣的:(Java)