多态(Polymorphism)
概述:
- 同一对象,在不同时刻表现出来的不同形态
- 有继承/实现关系
- 有方法重写
- 父类引用指向子类(接口引用指向实现类对象)
访问特点:
- 成员变量:编译看左,运行看左
- 成员方法:编译看左,运行看右
- [成员变量跟方法访问不同是因为方法有重写,变量没有]
多态好处:
- 提高程序的扩展性
- 定义方法时,使用父类型作为参数,使用时,使用子类型参与操作
多态弊端:
- 不能使用子类特有功能
#▲对象的多态:
- 一个对象的编译类型和运行类型可以不一致
- 编译类型在定义对象时,就确定了,不能改变
- 运行类型可变
- 编译看左运行看右
- [Animal animal = new cat(); animal的编译类型是Animal运行类型是cat]
向上转型:
- 父类引用指向子类对象
- 语法:
- 父类类型 引用名 = new 子类类型();
- 特点:
- 编译看左运行看右
- 可以调用父类的所有成员不能调用子类特有成员
向下转型:
- 语法:
- 子类类型 引用名 = (子类类型) 父类引用;
- 特点
- 只能强转父类的引用,不能强转父类的对象
- 要求父类的引用必须指向的是当前目标的类型对象
- 可以调用子类类型中的所有成员
instanceOf比较操作符:
- 用于判断对象的[运行]类型是否为xx类型或xx类型的子类型
#▲java的动态绑定机制:
- 当调用对象方法的时候,该方法会和该对象的内存地址/运行类型绑定
当调用对象的属性时,没有多态绑定机制,哪里声明哪里使用 :::
public class PolyDetail{
public static void main(String[] args) {
Base base = new Sub();
System.out.println(base.count);//10
Sub sub = new Sub();
System.out.println(sub.count);//20
}
}
class Base {//子类
int count = 10;//属性
}
class Sub extends Base {
int count = 20;
}
```java //数组定义类型为父类类型,里面保存的实际元素类型为子类型 public static void main(String[] args) { /*创建一个person对象 两个student跟teacher对象
统一放在数组中 并调用父类的say()方法*/
person[] persons = new person[5];//对象数组、 persons[0] = new person(“jack”, 20); persons[1] = new Student(“mary”, 30, 100); persons[2] = new Student(“Mike”, 25, 80); persons[3] = new Teacher(“king”, 50, 30000); persons[4] = new Teacher(“scott”, 48, 20000);
//循环遍历多态数组,调用say for (int i = 0; i < persons.length ; i++) {
//person[i]编译类型是person 运行类型是根据实际情况由JVM判定
System.out.println(persons[i].say());//动态绑定机制
//调用子类特有方法
if (persons[i] instanceof Student) {//判断persons[i]的运行类型是不是Student
Student student = (Student)persons[i];//向下转型 强转
student.study();
//缩写 ((Student)persons[i]).study;
System.out.println(persons[i]);
} else if (persons[i] instanceof Teacher) {
((Teacher)persons[i]).teach();
} else if (persons[i] instanceof person) {
} else {
System.out.println("类型有误!");
}
} } //父类 public class person { private String name; private int age; /*
无参带参构造方法
setget方法
*/ //返回名字年龄 public String say() {
return "名字: " + name + " 年龄: " + age;
} }
//教师子类 public class Teacher extends person{ private double salary;
public Teacher(String name, int age, double salary) {
super(name, age);
this.salary = salary;
}
//setget方法
@Override
public String say() {
return "教师: " + super.say() + " salary: " + salary;
}
public void teach() {
System.out.println("教师" + getName() + "正在授课");
}
}
//学生子类 public class Student extends person{ private double score;
public Student(String name, int age, double score) {
super(name, age);
this.score = score;
}
//setget方法
@Override
public String say() {
return "学生: " + super.say() + " score: " + score;
}
public void study() {
System.out.println("学生" + getName() + "正在听讲");
}
}
```java
//方法定义的形参类型为父类类型,实参类型允许为子类类型
/*
定义员工类Employee 包含姓名 月工资salary 以及计算年工资getAnnual的方法
普通员工经理继承员工 经理多了奖金bonus和管理manage方法 员工多了work方法
普通员工跟经理重写getAnnual方法
测试类中添加showEmpAnnual(Employee e) 实现获取任何员工对象的年薪
并在main调用该方法e.getAnnual()
测试类中添加一个方法 tesWork 如果是普通员工调用work方法
如果是经理调用manage方法
*/
public class PloyParameter {
public static void main(String[] args) {
Worker tom = new Worker("tom", 1000);
Manager milan = new Manager("milan", 5000, 10000);
PloyParameter ployParameter = new PloyParameter();
ployParameter.showEmpAnnual(tom);
ployParameter.showEmpAnnual(milan);
ployParameter.tesrWork(tom);
ployParameter.tesrWork(milan);
}
//调用年薪方法
public void showEmpAnnual(Employee e) {
System.out.println(e.getName() + "的年薪有: " + e.getAnnual());
}
//添加方法 分别调用不同子类方法
public void tesrWork(Employee e) {
if (e instanceof Worker) {
((Worker) e).work();
} else if (e instanceof Manager) {
((Manager) e).manage();
} else {
System.out.println("不做处理");
}
}
}
//父类
public class Employee {
private String name;
private double salary;
/*
无参带参构造方法
setget方法
*/
//得到年工资的方法
public double getAnnual() {
return 12 * salary;
}
}
//员工
public class Worker extends Employee {
public Worker(String name, double salary) {
super(name, salary);
}
public void work() {
System.out.println("员工: " + getName() + " is working!");
}
@Override
public double getAnnual() {//普通员工没有奖金 直接调用父类方法
return super.getAnnual();
}
}
//经理
public class Manager extends Employee{
private double bonus;
public Manager(String name, double salary, double bonus) {
super(name, salary);
this.bonus = bonus;
}
//setget方法
public void manage() {
System.out.println("经理: " + getName() + " is manageing!");
}
@Override
public double getAnnual() {
return super.getAnnual() + bonus;
}
}