目录
JAVA面向对象编程有三大特性:封装、继承、多态。
多态就是不同对象对同一物体或事件发出不同的反应或响应。比如stuendt是一个父类,那么在操场上上体育课的学生和在教室里面的学生就是它的子类。这时上课铃声响了,上体育课的学生去操场,在教室里面上课的学生则是回教室,不同的学生有着不同的反应,这就是多态。
实现多态的条件
实现多态的条件:
1.继承:必须要有子类继承父类的继承关系。
2.重写:子类需要对父类中的一些方法进行重写,然后调用方法时就会调用子类重写的方法而不是原本父类的方法。
3.向上转型:在多态中需要将子类的引用赋给父类对象,只有这样该引用才能够具备技能调用父类的方法和子类的方法。
多态的具体体现
1) 方法的多态
2) 对象的多态
核心:
1.一个对象的编译类型和运行类型可以不一致如:Animal animal=new Dog();animal=new Cat();Cat和Dog是Animal的子类2.编译类型在定义对象是就确定,不能改变3.运行类型可以改变4.编译类型看定义时=的左边,运行类型看右边5.对象能调用那些方法成员是由其编译类型决定的
向上转型
向上转型 : 父类的引用指向了子类的对象语法:父类类型引用名 = new 子类类型 ();Animal animal = new Cat();Object obj = new Cat();// 可以吗 ? 可以 Object 也是 Cat 的父类向上转型调用方法的规则如下 :(1) 可以调用父类中的所有成员 ( 需遵守访问权限 )(2) 但是不能调用子类的特有的成员(#) 因为在编译阶段,能调用哪些成员 , 是由编译类型来决定的animal.catchMouse(); 错误(4) 最终运行效果看子类 ( 运行类型 ) 的具体实现 , 即调用方法时,按照从子类 ( 运行类型 ) 开始查找方法,然后调用,规则我前面我们讲的方法调用规则一致。
向下转型:
(1) 语法:子类类型 引用名 = (子类类型)父类引用 ;问一个问题 ? cat 的编译类型 Cat, 运行类型是 CatCat cat = (Cat) animal;cat.catchMouse();// 猫抓老鼠(2) 要求父类的引用必须指向的是当前目标类型的对象
JAVA的动态绑定机制
1.当调用对象方法的时候,该方法会和该对象的内存地址/运行类型(也就是与运行类型)绑定(意思就是如:有一个Cat类,Cat类中有一个cay方法,这个方法会和Cat类发生动态绑定)
2.当调用对象属性时,没有动态绑定机制,哪里声明,哪里使用
package com.hspedu.poly_.dynamic_;
public class DynamicBinding {
public static void main(String[] args) {
//a 的编译类型 A, 运行类型 B
A a = new B();//向上转型
System.out.println(a.sum());//?40 -> 30
System.out.println(a.sum1());//?30-> 20
}
}
class A {//父类
public int i = 10;
//动态绑定机制:
public int sum() {//父类 sum()
return getI() + 10;//20 + 10
}
public int sum1() {//父类 sum1()
return i + 10;//10 + 10
}
public int getI() {//父类 getI
return i;
}
}
class B extends A {//子类
public int i = 20;
// public int sum() {
// return i + 20;
// }
public int getI() {//子类 getI()
return i;
}
// public int sum1() {
// return i + 10;
// }
}
多态的应用
数组的定义类型为父类类型,里面保存的实际元素类型为子类类型
现有一个继承结构如下:要求创建1个Person、2个Student对象和2个Teacher对象,统一放在数组中,并调用每个对象的say方法
package com.java.poly_.polyarr;
public class PolyArray {
public static void main(String[] args) {
Person[] persons=new Person[5];
persons[0]=new Person("jack",20);
persons[1]=new Student("jack",18,100);
persons[2]=new Student("smith",19,99);
persons[3]=new Teacher("scott",300,20000);
persons[4]=new Teacher("king",50,25000);
//循环遍历多态数组 编译类型是person
for(int i=0;i<persons.length;i++){
System.out.println(persons[i].say()); //动态绑定机制
}
}
}
class Person {
private String name;
private 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;
}
public String say(){
return name+"\t"+age;
}
}
class Student extends Person{
private double sore;
public Student(String name, int age, double sore) {
super(name, age);
this.sore = sore;
}
public double getSore() {
return sore;
}
public void setSore(double sore) {
this.sore = sore;
}
//重写
@Override
public String say() {
return super.say()+"sore"+sore;
}
}
class Teacher extends Person{
private double salary;
public Teacher(String name, int age, double salary) {
super(name, age);
this.salary = salary;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
@Override
public String say() {
return super.say()+"salary="+salary;
}
}
调用子类中的方法
package com.java.poly_.polyarr;
public class PolyArray {
public static void main(String[] args) {
Person[] persons=new Person[5];
persons[0]=new Person("jack",20);
persons[1]=new Student("jack",18,100);
persons[2]=new Student("smith",19,99);
persons[3]=new Teacher("scott",300,20000);
persons[4]=new Teacher("king",50,25000);
//循环遍历多态数组 编译类型是person
for(int i=0;i<persons.length;i++){
System.out.println(persons[i].say()); //动态绑定机制
if(persons[i] instanceof Student){
Student student=(Student)persons[i];
student.study();
//也可以一步 ((Student)persons[i]).study();
}else if(persons[i] instanceof Teacher){
Teacher teacher=(Teacher)persons[i];
teacher.teach();
}else if(persons[i] instanceof Person){
System.out.println("有误");
}
}
}
}
多态参数
要求:定义员工类Employee, 包含姓名和工资, 包含姓名和月工资,计算年工资getAnnual的方法。普通员工和经理继承了员工类,经理类多了奖金bonus属性和管理mange方法,普通员工多了work方法。普通员工和经理需要重写计算工资getAnnual方法。
父类员工
package com.hansp.poly.polypar;
public class Employee {
private String name;
private int salary;
public Employee(String name, int salary) {
this.name = name;
this.salary = salary;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
public int getAnnual(){
return salary*12;
}
}
子类经理
package com.hansp.poly.polypar;
public class manager extends Employee {
private int bonus;
public manager(String name, int salary, int bonus) {
super(name, salary);
this.bonus = bonus;
}
public void manage(){
System.out.println("经理管事");
}
public int getBonus() {
return bonus;
}
public void setBonus(int bonus) {
this.bonus = bonus;
}
@Override
public int getAnnual() {
return super.getAnnual()+getBonus();
}
}
子类员工
package com.hansp.poly.polypar;
public class staff extends Employee {
public void work(){
System.out.println("员工工作");
}
public staff(String name, int salary) {
super(name, salary);
}
@Override
public int getAnnual() {
return super.getAnnual();
}
}
测试类
package com.hansp.poly.polypar;
public class Demo {
public static void main(String[] args) {
manager a = new manager("小王", 8000, 2000);
staff b = new staff("小袁", 5000);
Demo c=new Demo();
c.show(a);
c.show(b);
c.testWork(a);
c.testWork(b);
}
public void show(Employee e)//展现员工的年工资
{
System.out.println(e.getAnnual());
}
public void testWork(Employee e){
if(e instanceof manager)
{
manager a=(manager) e;
a.manage();
}
if(e instanceof staff){
staff a=(staff) e;
a.work();
}
}
}