参考《Java核心技术卷1》
多态与动态绑定
Employee.java
package inheritance;
import java.time.LocalDate;
public class Employee {
private final String name; // 姓名
private double salary; // 薪水
private final LocalDate hireDay; // 入职日期
public Employee(String name, double salary, int year, int month, int day) {
this.name = name;
this.salary = salary;
hireDay = LocalDate.of(year, month, day);
}
public String getName() {
return name;
}
public double getSalary() {
return salary;
}
public LocalDate getHireDay() {
return hireDay;
}
public void raiseSalary(double byPercent) {
double raise = salary * byPercent / 100;
salary += raise;
}
}
经理.java
package inheritance;
public class Manager extends Employee {
private double bonus; // 奖金
public Manager(String name, double salary, int year, int month, int day) {
super(name, salary, year, month, day);
}
public double getSalary() {
double baseSalary = super.getSalary(); // 获取基本工资
return baseSalary + bonus; // 薪水=基本工资+奖金
}
public void setBonus(double bonus) {
this.bonus = bonus;
}
}
经理Test.java
package inheritance;
public class ManagerTest {
public static void main(String[] args) {
Manager boss = new Manager("张三", 8000, 2017, 12, 15);
boss.setBonus(500);
Employee[] staff = new Employee[3];
staff[0] = boss;
staff[1] = new Employee("李四", 5000, 2019, 10, 1);
staff[2] = new Employee("王五", 4000, 2020, 3, 15);
for (Employee e : staff) {
System.out.printf("%s, %.2f\n", e.getName(), e.getSalary());
}
}
}
输出:
张三, 8500.00
李四, 5000.00
王五, 4000.00
这里的e被声明为Employee类型,却引用了Manager类型的对象!这是合法的。并且,观察执行结果,e.getSalary()
会选出正确的getSalary
方法。
进一步简化、改写代码:
package inheritance;
public class ManagerTest {
public static void main(String[] args) {
Manager boss = new Manager("张三", 8000, 2017, 12, 15);
boss.setBonus(500);
Employee e = new Employee("李四", 5000, 2019, 10, 1);;
System.out.printf("%s, %.2f\n", e.getName(), e.getSalary());
// => 李四, 5000.00
e = boss;
System.out.printf("%s, %.2f\n", e.getName(), e.getSalary());
// => 张三, 8500.00
}
}
实际上,e既可以引用Employee类型的对象,也可以引用Manager类型的对象。
当e引用Employee对象时,e.getSalary()
调用的是Employee类中的getSalary
方法;当e引用Manager对象时,e.getSalary()
调用的则是Manager类中的getSalary
方法。虚拟机知道e实际引用的对象类型,因此能够调用正确的方法。
一个对象变量(例如,变量e)可以指示多种实际类型,这一点称为多态(polymorphism)。在运行时能够自动地选择适当的方法,这称为动态绑定(dynamic binding)。
继承层次结构
秘书.java
package inheritance;
public class Secretary extends Employee {
public Secretary(String name, double salary, int year, int month, int day) {
super(name, salary, year, month, day);
}
@Override
public double getSalary() {
System.out.println("秘书类中定义的getSalary被调用了");
return super.getSalary();
}
}
总经理Test.java
package inheritance;
public class ExecutiveTest {
public static void main(String[] args) {
Employee[] staff = new Employee[3];
staff[0] = new Secretary("小张三", 8000, 2024, 10, 10);
staff[1] = new Programmer("李四儿", 20000, 2024, 10, 10);
staff[2] = new Executive("小王五", 15000, 2024, 10, 10);
for (Employee e : staff) {
System.out.printf("%s, %.2f\n", e.getName(), e.getSalary());
}
// 上面循环语句的等价顺序语句是什么?写完后请改成等价的顺序语句
// 一个对象变量可以指示多种实际类型即"多态"
}
}
多态
package inheritance;
public class MyTest {
public static void main(String[] args) {
// 1 可将子类对象赋给超类变量
Employee e;
e = new Employee("张三", 1000, 2024, 9, 30); //"需要"一个员工类对象
e = new Manager("李四", 1000, 2024, 9, 30); //把经理类放这边也可以
// 2 当超类变量引用子类对象可以调用哪些方法?
Manager m = new Manager("李大头", 1000, 2024, 9, 30);
Employee aEmployee = m; //m与aEmployee引用了同一个对象!
//但"编译器"只将aEmployee看成是一个Employee对象
m.setBonus(500); //m是Manager类变量,调用Manager类中定义的方法是合法的!
//aEmployee.setBonus(500); //这句合法吗?如果不合法是为什么?
// 3 子类变量不能引用超类对象
//Manager manager = new Employee("李大头", 1000, 2024, 9, 30);
//上面代码能运行吗?如果如果不能原因是什么?
//怎样解决该问题?前提是什么?
}
}
PrimaryStudent练习
https://liaoxuefeng.com/books/java/oop/basic/inherit/index.html
public class Main {
public static void main(String[] args) {
Person p = new Person("小明", 12);
Student s = new Student("小红", 20, 99);
// TODO: 定义PrimaryStudent,从Student继承,新增grade字段:
Student ps = new PrimaryStudent("小军", 9, 100, 5);
System.out.println(ps.getScore());
}
}
class Person {
protected String name;
protected int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
}
class Student extends Person {
protected int score;
public Student(String name, int age, int score) {
super(name, age);
this.score = score;
}
public int getScore() { return score; }
}
class PrimaryStudent extends Student {
protected int grade;
public PrimaryStudent(String name, int age, int score, int grade) {
super(name, age, score);
this.grade = grade;
}
}
标签:name,int,子类,getSalary,超类,Employee,new,public From: https://www.cnblogs.com/xkxf/p/18515122