实验六 继承定义与使用
第一部分:理论知识
1.继承
继承是用已有类来构建新类的一种机制。当定义了一个新类继承了一个类时,这个新类就继承了这个类的方法和域,同时在新类中添加新的方法和域以适应新的情况
继承是Java程序设计中的一项核心技术, 也是面向对象特征之一
继承的特点:a.具有层次结构
b.子类继承了父类的域和方法
2.类、超类和子类
类继承的格式:class (新类名)+ extends (已有类名)
已有类称为:超类(superclass)、基类(base class)或父类(parent class)、基类(base class)
新类称作:子类(subclass)、派生类(derivedclass)或孩子类(child class)、派生类(derivedclass)或孩子类(child class)
3.super关键字
super是一个指示编译器调用超类方法的特有关键字,它不是一个对象的引用,不能将super赋给另一个对象变量
super关键字一般有两个用途:一是调用超类的方法(格式:super.方法名()),二是调用超类的构造公式(:super())
4.继承层次
从一个超类扩展而来的类集合称为继承层次(inheritance hierarchy)。在继承层次中,从某个类到其祖先的路径被称为该类的继承链(inheritance chain),并且Java不支持多继承
5.多态性
多态性泛指在程序中同一个符号在不同的情况下具有不同解释的现象
6.final类
不允许继承的类称为 final类,在类的定义中用final修饰符加以说明
7.强制类型转换
如果要把一个超类对象赋给一个子类对象变量,就必须进行强制类型转换。其格式为:子类对象=(子类)(超类对象)
8.Object:所有类的超类
Object类是Java中所有类的祖先——每一个类都由它扩展而来。在不给出超类的情况下,Java会自动把Object作为要定义类的超类,可以使用类型为Object的变量指向任意类型的对象,但要对它们进行专门的操作都要进行类型转换
9.访问修饰符
a.public:该类或该类均可访问
b.private:只有该类可以访问
c.protected:该类及其子类的成员可以访问,同一个包中的类也可以访问
d.默认:相同包中的类可以访问
10.枚举类
枚举类是一个类,它的隐含超类是java.lang.Enum
枚举值并不是整数或其它类型,是被声明的枚举类的自身实例,例如A是Grade的一个实例
枚举类不能有public修饰的构造函数,构造函数都是隐含private,编译器自动处理
第二部分:实验部分
1、实验目的与要求
(1) 理解继承的定义;
(2) 掌握子类的定义要求
(3) 掌握多态性的概念及用法;
(4) 掌握抽象类的定义及用途;
(5) 掌握类中4个成员访问权限修饰符的用途;
(6) 掌握抽象类的定义方法及用途;
(7)掌握Object类的用途及常用API;
(8) 掌握ArrayList类的定义方法及用法;
(9) 掌握枚举类定义方法及用途。
2、实验内容和步骤
实验1: 导入第5章示例程序,测试并进行代码注释。
测试程序1:
在elipse IDE中编辑、调试、运行程序5-1 (教材152页-153页) ;
掌握子类的定义及用法;
结合程序运行结果,理解并总结OO风格程序构造特点,理解Employee和Manager类的关系子类的用途,并在代码中添加注释。
1 package inheritance;
2
3 import java.time.*;
4
5 public class Employee
6 {
7 private String name;
8 private double salary;
9 private LocalDate hireDay;//构建三个public对象//
10
11 public Employee(String name, double salary, int year, int month, int day)
12 {
13 this.name = name;
14 this.salary = salary;
15 hireDay = LocalDate.of(year, month, day);
16 }
17
18 public String getName()
19 {
20 return name;
21 }
22
23 public double getSalary()
24 {
25 return salary;
26 }
27
28 public LocalDate getHireDay()
29 {
30 return hireDay;
31 }
32
33 public void raiseSalary(double byPercent)
34 {
35 double raise = salary * byPercent / 100;
36 salary += raise;
37 }
38 }
1 package inheritance;
2 //关键字extends表示继承,表明正在构造一个新类派生于一个已经存在的类//
3 public class Manager extends Employee
4 {
5 private double bonus;
6
7 /**
8 * @param name the employee's name
9 * @param salary the salary
10 * @param year the hire year
11 * @param month the hire month
12 * @param day the hire day
13 */
14 public Manager(String name, double salary, int year, int month, int day)
15 {//调用超类中含有的参数的构造器。//
16 super(name, salary, year, month, day);
17 bonus = 0;
18 }
19
20 public double getSalary()
21 {//子类要想访问超类中的方法用关键字super//
22 double baseSalary = super.getSalary();
23 return baseSalary + bonus;
24 }
25
26 public void setBonus(double b)
27 {
28 bonus = b;
29 }
30 }
理解并总结OO风格程序构造特点,理解Employee和Manager类的关系子类的用途
对于面向对象风格程序构造特点,大体有四个,即:抽象、封装、继承、多态。
继承:简单理解就是代码复用,把重复使用的代码精简掉的一种手段。封装:就是把一部分或全部属性和部分功能(函数)对外界屏蔽。多态:没有继承就没有多态,继承是多态的前提。虽然继承自同一父类,但是相应的操作却各不相同,这叫多态。
Employee和Manager使用extends关键字完成继承关系。用父类进行声明,子类进行构造。
测试程序2:
编辑、编译、调试运行教材PersonTest程序(教材163页-165页);
掌握超类的定义及其使用要求;
掌握利用超类扩展子类的要求;
在程序中相关代码处添加新知识的注释。
1 package abstractClasses;
2
3 /**
4 * This program demonstrates abstract classes.
5 * @version 1.01 2004-02-21
6 * @author Cay Horstmann
7 */
8 public class PersonTest//主类//
9 {
10 public static void main(String[] args)
11 {
12 Person[] people = new Person[2];
//用Employee类和Student类填充people数组//
13 14 // fill the people array with Student and Employee objects 15 people[0] = new Employee("Harry Hacker", 50000, 1989, 10, 1); 16 people[1] = new Student("Maria Morris", "computer science"); 17
18 // print out names and descriptions of all Person objects
//打印出所有person类的名字和其他描述//
19 for (Person p : people)
20 System.out.println(p.getName() + ", " + p.getDescription()); 21 }
22 }
1 package abstractClasses;
2
3 public class Student extends Person//子类:student类继承person类//
4 {
5 private String major;//创建一个私有属性major//
6
7 /**
8 * @param nama the student's name
9 * @param major the student's major
10 */
11 public Student(String name, String major)
12 {
13 // 将n传递给超类构造函数//
14 super(name);//子类直接调用超类中的name属性//
15 this.major = major;
16 }
17
18 public String getDescription()//访问器//
19 {
20 return "a student majoring in " + major;
21 }
22 }
package abstractClasses;
public abstract class Person//抽象类person//
{
public abstract String getDescription();
private String name;//创建一个私有属性//
public Person(String name)//构造器//
{
this.name = name;
}
public String getName()//访问器//
{
return name;
}
}
1 package abstractClasses;
2
3 import java.time.*;
4
5 public class Employee extends Person//子类:employee类继承person类//
6 {
7 private double salary;
8 private LocalDate hireDay;//构建两个私有属性//
9
10 public Employee(String name, double salary, int year, int month, int day)
11 {
12 super(name);//子类不再重新定义,直接调用超类中的name//
13 this.salary = salary;
14 hireDay = LocalDate.of(year, month, day);
15 }
16
17 public double getSalary()
18 {
19 return salary;
20 }
21
22 public LocalDate getHireDay()
23 {
24 return hireDay;
25 }
26
27 public String getDescription()
28 {
29 return String.format("an employee with a salary of $%.2f", salary);
30 }
31
32 public void raiseSalary(double byPercent)
33 {
34 double raise = salary * byPercent / 100;
35 salary += raise;
36 }//定义两个局部变量//
37 }
测试程序3:
编辑、编译、调试运行教材程序5-8、5-9、5-10,结合程序运行结果理解程序(教材174页-177页);
掌握Object类的定义及用法;
在程序中相关代码处添加新知识的注释。
1 package equals; 2 3 /** 4 * This program demonstrates the equals method. 5 * @version 1.12 2012-01-26 6 * @author Cay Horstmann 7 */ 8 public class EqualsTest 9 { 10 public static void main(String[] args) 11 { 12 Employee alice1 = new Employee("Alice Adams", 75000, 1987, 12, 15); 13 Employee alice2 = alice1; 14 Employee alice3 = new Employee("Alice Adams", 75000, 1987, 12, 15); 15 Employee bob = new Employee("Bob Brandson", 50000, 1989, 10, 1); 16 17 System.out.println("alice1 == alice2: " + (alice1 == alice2)); 18 19 System.out.println("alice1 == alice3: " + (alice1 == alice3)); 20 21 System.out.println("alice1.equals(alice3): " + alice1.equals(alice3)); 22 23 System.out.println("alice1.equals(bob): " + alice1.equals(bob)); 24 25 System.out.println("bob.toString(): " + bob); 26 27 Manager carl = new Manager("Carl Cracker", 80000, 1987, 12, 15); 28 Manager boss = new Manager("Carl Cracker", 80000, 1987, 12, 15); 29 boss.setBonus(5000);//子类中赋初值为空,主类中用更改器更改为5000// 30 System.out.println("boss.toString(): " + boss); 31 System.out.println("carl.equals(boss): " + carl.equals(boss)); 32 System.out.println("alice1.hashCode(): " + alice1.hashCode()); 33 System.out.println("alice3.hashCode(): " + alice3.hashCode()); 34 System.out.println("bob.hashCode(): " + bob.hashCode()); 35 System.out.println("carl.hashCode(): " + carl.hashCode()); 36 } 37 }
1 package equals;
2
3 public class Manager extends Employee//Manger类继承employee类//
4 {
5 private double bonus;//创建私有属性bonnus//
6
7 public Manager(String name, double salary, int year, int month, int day)
8 {
9 super(name, salary, year, month, day);//子类直接调用超类中已经创建的属性//
10 bonus = 0;
11 }
12
13 public double getSalary()
14 {
15 double baseSalary = super.getSalary();
16 return baseSalary + bonus;
17 }
18
19 public void setBonus(double bonus)
20 {
21 this.bonus = bonus;
22 }
23
24 public boolean equals(Object otherObject)//测试是否是同一个超类//
25 {
26 if (!super.equals(otherObject)) return false;
27 Manager other = (Manager) otherObject;
28 // super.equals checked that this and other belong to the same class
29 return bonus == other.bonus;
30 }
31
32 public int hashCode()//重写hashcode方法,让相等的两个对象获取的hascode也相等//
33 {
34 return java.util.Objects.hash(super.hashCode(), bonus);
35 }
36
37 public String toString()//把其他类型的数据转换为字符串类型的数据//
38 {
39 return super.toString() + "[bonus=" + bonus + "]";
40 }
41 }
1 package equals;
2
3 import java.time.*;
4 import java.util.Objects;
5
6 public class Employee
7 {
8 private String name;
9 private double salary;
10 private LocalDate hireDay;//创建三个私有属性//
11
12 public Employee(String name, double salary, int year, int month, int day)
13 {
14 this.name = name;
15 this.salary = salary;
16 hireDay = LocalDate.of(year, month, day);
17 }
18
19 public String getName()
20 {
21 return name;
22 }
23
24 public double getSalary()
25 {
26 return salary;
27 }
28
29 public LocalDate getHireDay()
30 {
31 return hireDay;
32 }
33
34 public void raiseSalary(double byPercent)
35 {
36 double raise = salary * byPercent / 100;
37 salary += raise;//定义两个局部变量//
38 }
39
40 public boolean equals(Object otherObject)
41 {
42 // 测试是否是同一个超类//
43 if (this == otherObject) return true;
44
45 // 显示参数为空,返回faulse//
46 if (otherObject == null) return false;
47
48 // 类不匹配,则不相等//
49 if (getClass() != otherObject.getClass()) return false;
50
51 // 其他对象是非空employee类//
52 Employee other = (Employee) otherObject;
53
54 // 测试是否具有相同的值//
55 return Objects.equals(name, other.name) && salary == other.salary && Objects.equals(hireDay, other.hireDay);
56 }
57
58 public int hashCode()
59 {
60 return Objects.hash(name, salary, hireDay);
61 }
62
63 public String toString()
64 {
65 return getClass().getName() + "[name=" + name + ",salary=" + salary + ",hireDay=" + hireDay
66 + "]";
67 }
68 }
测试程序4:
在elipse IDE中调试运行程序5-11(教材182页),结合程序运行结果理解程序;
掌握ArrayList类的定义及用法;
在程序中相关代码处添加新知识的注释。
1 package arrayList;
2
3 import java.time.*;
4
5 public class Employee
6 {
7 private String name;
8 private double salary;
9 private LocalDate hireDay;
10
11 public Employee(String name, double salary, int year, int month, int day)
12 {
13 this.name = name;
14 this.salary = salary;
15 hireDay = LocalDate.of(year, month, day);
16 }
17
18 public String getName()
19 {
20 return name;
21 }
22
23 public double getSalary()
24 {
25 return salary;
26 }
27
28 public LocalDate getHireDay()
29 {
30 return hireDay;
31 }
32
33 public void raiseSalary(double byPercent)
34 {
35 double raise = salary * byPercent / 100;
36 salary += raise;
37 }//定义两个局部变量//
38 }
测试程序5:
编辑、编译、调试运行程序5-12(教材189页),结合运行结果理解程序;
掌握枚举类的定义及用法;
在程序中相关代码处添加新知识的注释。
1 package enums;
2
3 import java.util.*;
4
5 /**
6 * This program demonstrates enumerated types.
7 * @version 1.0 2004-05-24
8 * @author Cay Horstmann
9 */
10 public class EnumTest//主类//
11 {
12 public static void main(String[] args)
13 {
14 Scanner in = new Scanner(System.in);
15 System.out.print("Enter a size: (SMALL, MEDIUM, LARGE, EXTRA_LARGE) ");
16 String input = in.next().toUpperCase();//字符串转换为大写//
17 Size size = Enum.valueOf(Size.class, input);
18 System.out.println("size=" + size);
19 System.out.println("abbreviation=" + size.getAbbreviation());
20 if (size == Size.EXTRA_LARGE)
21 System.out.println("Good job--you paid attention to the _.");
22 }
23 }
24
25 enum Size//枚举类型(都是enum的子类)//
26 {
27 SMALL("S"), MEDIUM("M"), LARGE("L"), EXTRA_LARGE("XL");//传入参数//
28
29 private Size(String abbreviation) { this.abbreviation = abbreviation; }
30 public String getAbbreviation() { return abbreviation; }
31
32 private String abbreviation;
33 }
实验2:编程练习1
定义抽象类Shape:
属性:不可变常量double PI,值为3.14;
方法:public double getPerimeter();public double getArea())。
让Rectangle与Circle继承自Shape类。
编写double sumAllArea方法输出形状数组中的面积和和double sumAllPerimeter方法输出形状数组中的周长和。
main方法中
1)输入整型值n,然后建立n个不同的形状。如果输入rect,则再输入长和宽。如果输入cir,则再输入半径。 2) 然后输出所有的形状的周长之和,面积之和。并将所有的形状信息以样例的格式输出。 3) 最后输出每个形状的类型与父类型,使用类似shape.getClass()(获得类型),shape.getClass().getSuperclass()(获得父类型);
思考sumAllArea和sumAllPerimeter方法放在哪个类中更合适?
输入样例:
1 3
2
3 rect
4
5 1 1
6
7 rect
8
9 2 2
10
11 cir
12
13 1
输出样例:
18.28
8.14
[Rectangle [width=1, length=1], Rectangle [width=2, length=2], Circle [radius=1]]
class Rectangle,class Shape
class Rectangle,class Shape
class Circle,class Shape
import java.util.Scanner;
public class Work
{
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
String rect = "rect";
String cir = "cir";
System.out.print("请输入所需图形的形状个数:");
int n = in.nextInt();
shape[] count = new shape[n];
for(int i=0;i<n;i++)
{
System.out.println("请输入图形形状:");
String input = in.next();
if(input.equals(rect))
{
double length = in.nextDouble();
double width = in.nextDouble();
System.out.println("长方形:"+"长:"+length+" 宽:"+width);
count[i] = new Rect(length,width);
}
if(input.equals(cir))
{
double radius = in.nextDouble();
System.out.println("圆:"+"半径:"+radius);
count[i] = new Cir(radius);
}
}
Work c = new Work();
System.out.println(c.sumAllPerimeter(count));
System.out.println(c.sumAllArea(count));
for(shape s:count)
{
System.out.println(s.getClass()+", "+s.getClass().getSuperclass());
}
}
public double sumAllArea(shape count[])
{
double sum = 0;
for(int i = 0;i<count.length;i++)
sum+= count[i].getArea();
return sum;
}
public double sumAllPerimeter(shape count[])
{
double sum = 0;
for(int i = 0;i<count.length;i++)
sum+= count[i].getPerimeter();
return sum;
}
}
1 public abstract class shape
2 {
3 double PI = 3.14;
4 public abstract double getPerimeter();
5 public abstract double getArea();
6 }
public class Rect extends shape
{
private double width;
private double length;
public Rect(double w,double l)
{
this.width = w;
this.length = l;
}
public double getPerimeter()
{
double Perimeter = 2*(length+width);
return Perimeter;
}
public double getArea()
{
double Area = length*width;
return Area;
}
}
1 public class Cir extends shape
2 {
3 private double radius;
4
5 public Cir(double radius2) {
6 // TODO Auto-generated constructor stub
7 }
8 public double getPerimeter()
9 {
10 double Perimeter=2*PI*radius;
11 return Perimeter;
12 }
13 public double getArea()
14 {
15 double Area=PI*radius*radius;
16 return Area;
17 }
18 }
结果
实验3:编程练习2
编制一个程序,将身份证号.txt 中的信息读入到内存中,输入一个身份证号或姓名,查询显示查询对象的姓名、身份证号、年龄、性别和出生地。
实验代码 1 import java.io.BufferedReader; 2 import java.io.File; 3 import java.io.FileInputStream; 4 import java.io.FileNotFoundException; 5 import java.io.IOException; 6 import java.io.InputStreamReader; 7 import java.util.ArrayList; 8 import java.util.Scanner; 9 10 public class Test{ 11 private static ArrayList<Person> Personlist; 12 public static void main(String[] args) { 13 Personlist = new ArrayList<>(); 14 Scanner scanner = new Scanner(System.in); 15 File file = new File("E:\WPS Office\身份证号.txt"); 16 try { 17 FileInputStream fis = new FileInputStream(file); 18 BufferedReader in = new BufferedReader(new InputStreamReader(fis)); 19 String temp = null; 20 while ((temp = in.readLine()) != null) { 21 22 Scanner linescanner = new Scanner(temp); 23 24 linescanner.useDelimiter(" "); 25 String name = linescanner.next(); 26 String ID = linescanner.next(); 27 String sex = linescanner.next(); 28 String age = linescanner.next(); 29 String birthplace =linescanner.nextLine(); 30 Person Person = new Person(); 31 Person.setname(name); 32 Person.setID(ID); 33 Person.setsex(sex); 34 Person.setage(age); 35 Person.setbirthplace(birthplace); 36 Personlist.add(Person); 37 38 } 39 } catch (FileNotFoundException e) { 40 System.out.println("查找不到信息"); 41 e.printStackTrace(); 42 } catch (IOException e) { 43 System.out.println("信息读取有误"); 44 e.printStackTrace(); 45 } 46 boolean isTrue = true; 47 while (isTrue) { 48 49 System.out.println("1.按姓名查找"); 50 System.out.println("2.按身份证号查找"); 51 System.out.println("3.退出"); 52 int nextInt = scanner.nextInt(); 53 switch (nextInt) { 54 case 1: 55 System.out.println("请输入姓名:"); 56 String Personname = scanner.next(); 57 int nameint = findPersonByname(Personname); 58 if (nameint != -1) { 59 System.out.println("查找信息为:姓名:" 60 + Personlist.get(nameint).getname() + " 身份证号:" 61 + Personlist.get(nameint).getID() +" 年龄:" 62 +Personlist.get(nameint).getage() +" 性别:" 63 +Personlist.get(nameint).getsex()+" 出生地:" 64 +Personlist.get(nameint).getbirthplace() 65 ); 66 } else { 67 System.out.println("此人不存在!"); 68 } 69 break; 70 case 2: 71 System.out.println("请输入身份证号"); 72 String PersonID = scanner.next(); 73 int IDint = findPersonByID(PersonID); 74 if (IDint != -1) { 75 System.out.println("查找信息为:姓名:" 76 + Personlist.get(IDint).getname() + "