目录
一、多态的注意事项和细节讨论
细节讨论案例
二、java的动态绑定机制
基本介绍
方法或对象具有多种形态称之为多态。是面向对象的第三大特征,多态是建立在封装和继承基础之上的
多态的具体体现
1.方法的多态:重写和重载就体现出多态
2.对象的多态:①一个对象的编译类型和运行类型可以不一致
②编译类型在定义对象时就已经确定了,不能再改变
③运行类型是可以变化的
④编译类型看定义时 = 号的左边,运行类型看 = 号的右边
一、多态的注意事项和细节讨论
调方法看运行类型,调属性看编译类型!!!
1.多态的前提是:两个对象(类)存在继承关系
2.多态的向上转型:①本质:父类的引用指向了子类的对象
②语法:父类类型 引用名 = new 子类类型();
③特点:编译类型看等号左边,运行类型看等号右边
可以调用父类中的所有成员(需遵守访问权限)
不能调用子类中特有成员
最终运行效果看子类的具体实现,即调用方法时从子类开始查找
3.多态的向下转型:①语法:子类类型 引用名 = (子类类型) 父类引用;
②只能强转父类的引用,不能强转父类的对象
③要求父类的引用必须指向的是当前目标类型的对象
④当向下转型后,可以调用子类类型中所有的成员
4.属性没有重写之说!属性的值看编译类型
public class PolyDetail02 { 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; //属性}
5、instanceof 比较操作符,用于判断对象的运行类型是否为XX类型或者XX类型的子类型
public class PolyDetail03 { public static void main(String[] args) { //instanceOf 比较操作符,用于判断对象的运行类型是否为 XX 类型或 XX 类型的子类型 BB bb = new BB(); System.out.println(bb instanceof BB); //true System.out.println(bb instanceof AA); //true Object obj = new Object(); System.out.println(obj instanceof AA); //false String str = "hello"; //System.out.println(str instanceof AA); //错误的 System.out.println(str instanceof Object); //true }}class AA {} //父类class BB extends AA {} //子类
细节讨论案例
public class PolyDetail { public static void main(String[] args) { //向上转型:父类的引用指向了子类的对象 //语法: 父类类型 引用名 = new 子类类型(); Animal animal = new Cat(); Object obj = new Cat(); //可以,Object 也是 Cat 的父类 //向上转型调用方法的规则如下: //1.可以调用父类中的所有成员(需遵守访问权限),但不能调用子类中特有的成员 //2.因为在编译阶段,能调用哪些成员,是由编译类型来决定的 //animal.catchMouse(); 错误的 //3.最终运行效果看子类的具体实现,即调用方法时,按照从子类开始查找方法,然后调用, //规则和我们前面讲的方法调用规则一致 animal.eat(); //猫吃鱼 animal.run(); //跑 animal.show(); //hello,你好 animal.sleep();//睡 //希望调用Cat的catchMouse方法 //多态的向下转型: //1.语法: 子类类型 引用名 = (子类类型)父类引用; //cat的编译类型是Cat,运行类型也是Cat Cat cat = (Cat) animal; cat.cathMouse(); //2.要求父类的引用必须指向的是当前目标类型的对象 //Dog dog = (Dog) animal; //错误的,不可以把猫对象强转成狗 }}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 cathMouse(){ System.out.println("猫抓老鼠"); }}public class Dog extends Animal {//Dog是Animal的子类}
二、java的动态绑定机制
1.当调用对象方法时,该方法会和该对象的内存地址(运行类型)绑定
2.当调用对象属性时,没有动态绑定机制,哪里声明哪里使用(首先按作用域查找,作用域如果没有则按继承机制继续查找)
public class DynamicBinding { public static void main(String[] args) { //java的动态绑定机制 //1.当调用对象方法时,该方法会和该对象的内存地址(运行类型)绑定 //2.当调用对象属性时,没有动态绑定机制,哪里声明,哪里使用(首先按作用域来找,作用域如果没有就按继承机制来找) //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 + 1 } 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 sum1() {// return i + 10;// } public int getI() {//子类 getI() return i; }}
三、多态的应用1.多态数组:数组的定义类型为父类,里面保存的实际元素类型为子类类型
public class PolyArray { public static void main(String[] args) { //应用实例:现有一个继承结构如下:要求创建 1 个 Person 对象、2 个 Student 对象 // 和 2 个 Teacher 对象, 统一放在数组中,并调用每个对象say 方法 Person[] persons = new Person[5]; persons[0] = new Person("jack", 20); persons[1] = new Student("mary", 19, 100); persons[2] = new Student("smith", 18, 75); persons[3] = new Teacher("scott", 30, 10000); persons[4] = new Teacher("king", 40, 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) { //判断person[i]的运行类型是不是Student ((Student) persons[i]).study(); } 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; //构造器 public Person(String name, int age) { this.name = name; this.age = age; } //say方法,返回名字和年龄 public String say(){ return name + "t" +age; } //get和set方法 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 class Teacher extends Person { //子类 //属性 private double salary; //构造器 public Teacher(String name, int age, double salary) { super(name, age); this.salary = salary; } //重写父类say方法 @Override public String say() { return super.say() + " 老师 salary=" + salary; } //特有的方法 public void teach(){ System.out.println("老师 " + getName() + " 正在讲java课程"); } //get和set方法 public double getSalary() { return salary; } public void setSalary(double salary) { this.salary = salary; }}public class Student extends Person { //子类 //属性 private double score; //构造器 public Student(String name, int age, double score) { super(name, age); this.score = score; } //重写父类say方法 @Override public String say() { return super.say() + " 学生 score=" + score; } //特有的方法 public void study(){ System.out.println("学生 " + getName() + " 正在学java..."); } //get和set方法 public double getScore() { return score; } public void setScore(double score) { this.score = score; }}
2.多态参数:方法定义的形参类型为父类类型,实参类型为子类类型
package com.learn.poly_.polyparameter;public class PolyParameter { public static void main(String[] args) { Worker tom = new Worker("tom", 2500); Manage milan = new Manage("milan", 5000, 20000); PolyParameter polyParameter = new PolyParameter(); polyParameter.showEmpAnnual(tom); polyParameter.showEmpAnnual(milan); polyParameter.testWork(tom); polyParameter.testWork(milan); } //showEmpAnnual(Employee e) //实现获取任何员工对象的年工资,并在 main 方法中调用该方法 [e.getAnnual()] public void showEmpAnnual(Employee e){ System.out.println(e.getAnnual());//动态绑定机制 } //添加一个方法,testWork,如果是普通员工,则调用 work 方法,如果是经理,则调用 manage 方法 public void testWork(Employee e){ if(e instanceof Worker){ ((Worker) e).work(); //有一个向下转型的操作 }else if(e instanceof Manage){ ((Manage) e).manage(); //有一个向下转型的操作 }else{ System.out.println("不做处理..."); } }}package com.learn.poly_.polyparameter;public class Employee { private String name; private double salary; public Employee(String name, double salary) { this.name = name; this.salary = salary; } //得到年工资的方法 public double getAnnual(){ return 12 * salary; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Double getSalary() { return salary; } public void setSalary(Double salary) { this.salary = salary; }}package com.learn.poly_.polyparameter;public class Manage extends Employee { private double bonus; public Manage(String name, double salary, double bonus) { super(name, salary); this.bonus = bonus; } //方法 public void manage(){ System.out.println("经理 " + getName() + "is manage"); } //重写获取年薪方法 @Override public double getAnnual() { return super.getAnnual() + bonus; } public double getBonus() { return bonus; } public void setBonus(double bonus) { this.bonus = bonus; }}package com.learn.poly_.polyparameter;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(); }}