1.定义
允许不同类的对象对同一消息做出响应,即同一消息可以根据发送对象的不同而采用多种不同的行为方式。
2.存在条件
2.1存在继承关系
2.2子类重写了父类方法
2.3父类类型的变量指向子类对象的引用(向上转型)
3.实现方式
3.1接口实现
3.2继承父类进行方法重写
3.3同一个类中进行方法重载
4.类型的强制转换
4.1转换格式:子类 新变量=(子类)变量(父类类型的引用变量指向子类对象)
4.2父类类型的变量可以转换成子类类型的变量,但是可能出现“类型转换异常”
4.3使用x instance A判断异常,要求x所属的类B与类A为父子关系:结果为true,不抛出异常
5.实例分析
实例一:
1 class A { 2 public String show(A obj) { 3 return ("A and A"); 4 } 5 public String show(D obj) { //方法的重载 6 return ("A and D"); 7 } 8 } 9 10 class B extends A { 11 public String show(B obj) { //方法的重载 12 return ("B and B"); 13 } 14 public String show(A obj) { //方法的重写 15 return ("B and A"); 16 } 17 } 18 19 class C extends B { 20 } 21 22 class D extends B { 23 } 24 25 public class Polymorphic { 26 public static void main(String[] args) { 27 A a1 = new A(); 28 B b = new B(); 29 C c = new C(); 30 D d = new D(); 31 //多态:父类类型的变量指向子类对象的引用 32 A a2 = new B(); 33 34 //多态的表现形式:相同类型的变量,调用相同的方法,产生不一样的结果。 35 System.out.println("1--" + a1.show(b)); 36 System.out.println("2--" + a1.show(c)); 37 System.out.println("3--" + a1.show(d)); 38 System.out.println("4--" + a2.show(b)); 39 System.out.println("5--" + a2.show(c)); 40 System.out.println("6--" + a2.show(d)); 41 System.out.println("7--" + b.show(b)); 42 System.out.println("8--" + b.show(c)); 43 System.out.println("9--" + b.show(d)); 44 } 45 }
运行结果:
1 1--A and A 2 2--A and A 3 3--A and D 4 4--B and A 5 5--B and A 6 6--A and D 7 7--B and B 8 8--B and B 9 9--A and D
详细说明:
当超类对象引用变量引用子类对象时,被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法,
但是这个被调用的方法必须是在超类中定义过的,也就是被子类覆盖的方法。方法的调用关系如下:
- this.method(O) // 该类自身的方法
- super.method(O) // 基类的方法
- this.method((super)O) // 该类自身的方法,参数向上转型
- super.method((super)O) // 基类的方法,参数向上转型
示例讲解:
a1.show(b):
1.a1是类型为A的引用变量,该变量指向A对象,b是B的一个实例;
2.在类A中查看是否存在show(B obj)方法,不存在;
3.查看类A是否存在超类(父类),不存在;
4.查看类A是否存在show(A obj)方法,存在;
注:(super) O即(super) B,即为A,则对应的方法为show(A obj));
5.a1是对本身对象的引用,不考虑方法的重写,答案为 A and A。
注:第1步是分析,第2-4步分别对应上面的this.show(O),super.show(O),this.show((super) O)
a1.show(c):
1.a1是类型为A的引用变量,该变量指向A对象,c是C的一个实例;
2.查看类A是否存在show(C obj)方法,不存在;
3.查看类A是否存在超类(父类),不存在;
4.查看类A是否存在show(B obj)方法,不存在;
5.查看类A是否存在超类(父类),不存在;
6.查看类A是否存在show(A obj)方法,存在;
7.a1是对本身对象的引用,不考虑方法的重写,答案为 A and A。
a2.show(b):
1.a2是类型为A的引用变量,该变量指向A对象,b是B的一个实例;
2.查看类A是否存在show(B obj)方法,不存在;
3.查看类A是否存在超类(父类),不存在;
4.查看类A是否有show(A obj)方法,存在;
5.a2是对子类B对象的引用,考虑方法的重写,在子类B中对类A的show(A obj)进行了重写,所以答案为B and A。
b.show(c):
1.b是类型为B的引用变量,该变量指向B对象,c是C的一个实例;
2.查看类B是否存在show(C obj)方法,不存在;
3.查看类A是否存在show(C obj)方法,不存在;
4.查看类B是否存在show(B obj)方法,存在;
5.b是对本身对象的引用,不考虑方法的重写,答案为B and B。
实例二:
1 public class Person { 2 public void walk(){ 3 System.out.println("走路"); 4 } 5 } 6 public class Man extends Person{ 7 public void walk(){ 8 System.out.println("男人快步走"); 9 } 10 public void work(){ 11 System.out.println("男人是个工作狂"); 12 } 13 } 14 15 public class Woman extends Person{ 16 public void walk(){ 17 System.out.println("女人漫步走"); 18 } 19 public void shopping(){ 20 System.out.println("女人是个购物狂"); 21 } 22 } 23 public class Test { 24 public static void main(String args[]){ 25 Person p1=new Person(); 26 27 //多态:父类类型的变量指向子类对象的引用 28 Person p2=new Man(); 29 Person p3=new Woman(); 30 31 //多态的表现形式:相同类型的变量,调用相同的方法,产生不一样的结果。 32 p1.walk(); 33 虚拟方法调用:当父类的方法被子类重写时,会调用子类重写的方法,而不是父类的方法。 34 p2.walk(); 35 p3.walk(); 36 37 在多态的情况下,只能调用父类的方法和被子类重写的方法;如果向调用子类的方法,需要进行类型的前置转换 38 // p2.work(); 错误 39 40 41 Man m=(Man) p2; 42 m.work(); 43 Woman w=(Woman) p3; 44 w.shopping(); 45 46 父类类型的变量可以转换成子类类型的变量,但是可能出现“类型转换异常”。 47 /*Woman w=(Woman) p2; 48 w.shopping();*/ 49 50 /*instanceof操作符 51 x instance A,要求x所属的类B与类A为父子关系 52 instanceof可以检测是否会抛出类型转换异常,返回true表示可以转换类型*/ 53 System.out.println(p2 instanceof Man); 54 } 55 }
!!!