import java.util.*; /** * This program demonstrates inheritance. * @version 1.21 2004-02-21 * @author Cay Horstmann */ public class ManagerTest { public static void main(String[] args) { // construct a Manager object Manager boss = new Manager("Carl Cracker", 80000, 1987, 12, 15); boss.setBonus(5000); Employee[] staff = new Employee[3]; // fill the staff array with Manager and Employee objects staff[0] = boss; staff[1] = new Employee("Harry Hacker", 50000, 1989, 10, 1); staff[2] = new Employee("Tommy Tester", 40000, 1990, 3, 15); // print out information about all Employee objects for (Employee e : staff) System.out.println("name=" + e.getName() + ",salary=" + e.getSalary()); } } class Employee { public Employee(String n, double s, int year, int month, int day) { name = n; salary = s; GregorianCalendar calendar = new GregorianCalendar(year, month - 1, day); hireDay = calendar.getTime(); } public String getName() { return name; } public double getSalary() { return salary; } public Date getHireDay() { return hireDay; } public void raiseSalary(double byPercent) { double raise = salary * byPercent / 100; salary += raise; } private String name; private double salary; private Date hireDay; } class Manager extends Employee { /** * @param n the employee's name * @param s the salary * @param year the hire year * @param month the hire month * @param day the hire day */ public Manager(String n, double s, int year, int month, int day) { super(n, s, year, month, day); bonus = 0; } public double getSalary() { double baseSalary = super.getSalary(); return baseSalary + bonus; } public void setBonus(double b) { bonus = b; } private double bonus; }
1)绘制UML类图,要体现类之间的关系。
java
2)文件第26行e.getSalary(),究竟是调用Manager类的仍是Employee类的getSalary方法?
staff[0] 调用的是Manager类的getSalary方法;
staff[1] 和 staff[2] 调用的是Employee类的getSalary方法。
由于 staff[0] 被幅值为 Manager 类,子类会覆盖父类的方法,因此 staff[0] 优先调用Manager类的getSalary方法。函数
3)Manager类的构造函数使用super调用父类的构造函数实现了代码复用,这样有什么好处?为何不把父类构造函数中的相关代码复制粘贴到Manager的构造函数中,这样看起来不是更直观吗?
采用super关键字调用父类的构造函数能够减小重复代码,同时由于子类继承父类,会继承到父类中的数据,因此必需要调用父类中的构造函数看父类是如何对本身的数据进行初始化的。因此子类在进行对象初始化时,先调用父类的构造函数,这就是子类的实例化过程。
注意:
一、子类中全部的构造函数都会默认访问父类中的空参数的构造函数,由于每个子类构造内第一行都有默认的语句super();
二、若父类中没有空参数的构造函数,那么子类的构造函数内,必须经过super语句指定要访问的父类中的构造函数;
三、若子类构造函数中用this来指定调用子类本身的构造函数,那么被调用的构造函数也同样会访问父类中的构造函数。this
for (Employee e : staff) System.out.println("name=" + e.getName() + ",salary=" + e.getSalary()); }
抽象类是为了把相同的但不肯定的东西的提取出来 ,在Game中都要实行经过循环猜数字这一段代码,抽象类GuessGame实现了这一方法,那么游戏的其余部分只要直接继承这个抽象类,再实现其余方法就能够了,抽象类构造出一个固定的一组行为的抽象描述,可是这组行为却可以有任意个可能的具体实现方式,这样改造有利于实现决多重继承问题。spa
若是继承自这个抽象类的全部子类都存在这个方法并其的实现都是同样的时候,则这个方法不须要声明为abstract直接实现便可。相反,若是子类存在这一行为但具体实现是不同的,则应该声明为abstract来让子类实现。
例如:
作一个接口叫作飞行FlyAnimalAction,里面定义一个方法叫作flying,再定义一个方法叫作eat
作一个类叫作蚊子实现接口,蚊子要实现flying方法,实现本身的eat方法
作一个类叫作苍蝇实现接口,苍蝇也要实现flying方法,实现本身的eat方法
你发现全部会飞的动物都要实现这个接口,很麻烦,不如
作一个抽象类FlyAnimal,而后实现上面的接口
在里面实现flying这个方法,由于大部分的飞行动做是同样的,而eat方法则继续写成抽象方法,由于大部分的动物吃东西是不同的设计
public abstract void print(String text); public abstract void println(String text); public abstract int nextInt();
不变的是go函数,即抽象类中直接实现的方法。code