多态(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);//10Sub 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]的运行类型是不是StudentStudent 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方法@Overridepublic 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方法@Overridepublic 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!");}@Overridepublic 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!");}@Overridepublic double getAnnual() {return super.getAnnual() + bonus;}}
