目录
1.多[多种]态[状态]基本介绍
方法或对象具有多种形态。是面向对象的第三大特征,多态是建立在封装和继承基础之上的。
2.多态的具体表现
-
方法的多态:重写和重载就体现多态
public class demo01 { public static void main(String[] args) { //方法重载体现多态 A a = new A(); //这里我们传入不同的参数,就会调用不同 sum 方法,就体现多态 System.out.println(a.sum(10, 20)); System.out.println(a.sum(10, 20, 30)); //方法重写体现多态 B b = new B(); a.say(); b.say(); } }
class B { //父类 public void say() { System.out.println("B say() 方法被调用..."); } } class A extends B {//子类 public int sum(int n1, int n2) {//和下面 sum 构成重载 return n1 + n2; } public int sum(int n1, int n2, int n3) { return n1 + n2 + n3; } }
-
对象的多态
-
一个对象的编译类型和运行类型可以不一致(可一致)
-
编译类型在定义对象,就确定了,不能改变
-
运行类型是可以变化的
-
编译类型看定义时 = 号的左边,运行类型看 = 号的右边
-
Animal animal = new Dog(); //animal 编译类型就是 Animal , 运行类型 Dog animal = new Cat(); //animal 编译类型 Animal,运行类型就是 Cat
3.注意事项
-
多态的前提是:两个对象(类)存在继承关系
-
多态的向上转型
-
本质:父类的引用指向了子类的对象
-
语法:父类类型 引用名 = new 子类类型();
-
特点:编译类型看左边,运行类型看右边。可以调用父类中的所有成员(遵守访问权限),不能调用子类的特有成员;运行效果看子类的具体实现。即调用方法时,按照从子类(运行类型)开始查找方法后调用
-
public class Animal { String name = "动物"; int age = 10; public void sleep(){ System.out.println("睡"); } public void run(){ System.out.println("跑"); } public void eat(){ System.out.println("吃"); } public void show(){ System.out.println("hello,你好"); } }
public class Cat extends Animal{ public void eat(){//方法重写 System.out.println("猫吃鱼"); } public void catchMouse(){//Cat 特有方法 System.out.println("猫抓老鼠"); } }
public class TestAniaml { public static void main(String[] args) { //向上转型: 父类的引用指向了子类的对象 //语法:父类类型引用名 = new 子类类型(); Animal animal = new Cat(); Object obj = new Cat(); //可以吗? 可以 Object 也是 Cat 的父类 //animal.catchMouse();错误 animal.eat();//猫吃鱼.. animal.run();//跑 animal.show();//hello,你好 animal.sleep();//睡 } }
-
多态的向下转型
-
语法:子类类型 引用名 =(子类类型)父类引用;
-
只能强转父类的引用,不能强转父类的对象
-
要求父类的引用必须指向的是当前目标类型的对象
-
可以调用子类类型中所有成员
//多态的向下转型 //(1)语法:子类类型 引用名 =(子类类型)父类引用; // cat 的编译类型 Cat,运行类型是 Cat Cat cat = (Cat) animal; cat.catchMouse();//猫抓老鼠 //(2)要求父类的引用必须指向的是当前目标类型的对象 Dog dog = (Dog) animal; //可以吗? 不可以,相当于将猫强转为一个狗 System.out.println("ok~~");
-
-
属性没有重写之说!属性的值看编译类型
public class bianyi { 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;//属性 }
-
instanceOf 比较操作符,用于判断对象的运行类型是否为 XX 类型或 XX 类型的子类型
public class instanceOf { public static void main(String[] args) { BB bb = new BB(); System.out.println(bb instanceof BB);// true System.out.println(bb instanceof AA);// true //aa 编译类型 AA, 运行类型是 BB //BB 是 AA 子类 AA aa = new BB(); System.out.println(aa instanceof AA);// true System.out.println(aa instanceof BB);// true } } class AA { } class BB extends AA { }
4.Java 重要特性: 动态绑定机制
-
当调用对象方法的时候,该方法会和该对象的内存地址/运行类型绑定
-
当调用对象属性时,没有动态绑定机制,哪里声明哪里使用
5.多态的应用
-
多态数组
数组的定义类型为父类类型,里面保存的实际元素类型为子类类型
eg: 应用实例:现有一个继承结构如下:要求创建 1 个 Person 对象、2 个Student 对象和 2 个 Teacher 对象, 统一放在数组中,并调用每个对象say 方法. 并且实现调用子类特有的方法,比如Teacher 有一个 teach , Student 有一个 study
定义父类实体类Person
public 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; } }
定义学生类子类
public class Student extends Person{ private double score; public Student(String name, int age, double score) { super(name, age); this.score = score; } public double getScore() { return score; } public void setScore(double score) { this.score = score; } @Override public String say() { return super.say() + score; } //特有的方法 public void study() { System.out.println("学生 " + getName() + " 正在学 java..."); } }
定义老师类子类
public 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; } //特有方法 public void teach() { System.out.println("老师 " + getName() + " 正在讲 java 课程..."); } }
测试调用
public class Tset { public static void main(String[] args) { Person[] person = new Person[5]; person[0] = new Person("a",11); person[1] = new Student("b",12,99); person[2] = new Student("c",13,34); person[3] = new Teacher("d",14,10000); person[4] = new Teacher("e",15,20000); //循环遍历多态数组,调用 say for (int i = 0; i < person.length; i++) { // person[i] 编译类型是 Person ,运行类型是是根据实际 情况有 JVM 来判断 System.out.println(person[i].say());//动态绑定机制 // 使用 类型判断 + 向下转型. if(person[i] instanceof Student){ Student student = (Student) person[i]; student.study(); // ((Student)person[i]).study(); }else if(person[i] instanceof Teacher){ ((Teacher)person[i]).teach(); }else if(person[i] instanceof Person){ }else{ System.out.println("false"); } } } }
-
多态参数
方法定义的形参为父类类型,实参类型允许子类类型
eg:
测试类
public class employeeTest { public static void main(String[] args) { Work a = new Work("a",1500); Manager b = new Manager("b",10000,125); employeeTest et = new employeeTest(); et.showEmpAnnual(a); et.showEmpAnnual(b); et.testWork(a); et.testWork(b); } //showEmpAnnual(Employee e) public void showEmpAnnual(Employee e){ System.out.println(e.getAnnual()); } public void testWork(Employee e){ if(e instanceof Work){ ((Work) e).work(); }else if(e instanceof Manager){ ((Manager) e).manage(); }else{ System.out.println("false"); } } }
雇员父类
public class Employee { private String name; private double mouth; public Employee(String name, double mouth) { this.name = name; this.mouth = mouth; } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getMouth() { return mouth; } public void setMouth(double mouth) { this.mouth = mouth; } public double getAnnual(){ return mouth *12; } }
普通员工子类
public class Work extends Employee{ public Work(String name, double mouth) { super(name, mouth); } 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 mouth, double bonus) { super(name, mouth); this.bonus = bonus; } public double getBonus() { return bonus; } public void setBonus(double bonus) { this.bonus = bonus; } @Override public double getAnnual() { return super.getAnnual()+bonus; } public void manage(){ System.out.println("经理" + getName() + "is managing"); } }