多态
多态是指对不同的子类调用相同的方法,输出的结果不同。意思是程序在编译的时候并不知道要调用哪个类的方法,必须等到程序运行的时候才能决定。
对象多态类型
对象的多态类型一共有两种:静态类型,动态类型。静态类型是对类而言,在程序运行的过程为中,静态类型的类会根据引用对象的改变而改变。动态类型对对象而言,一但一个对象被new方法创建了,那这个对象就是内存中的有效的动态类型。
检验动态类型的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| public class Test { public void exempleDeMecanismesTestantLeTypeDynamique(Object o) { // o是对动态类型对象的引用 // o可以是类A,类B // 或者是C的实例,或者D的实例
//第一种方法 getClass System.out.println(o.getClass().getName() ) ; if (o.getClass() == A.class) { // 只有当o的动态类型是A的时候才会进入if ... }
// 第二种方法 instanceof if (o instanceof A) { //o是动态类型A或者A的子类 ... } } }
|
例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| public class A { public String show(D obj) { return ("A and D"); }
public String show(A obj) { return ("A and A"); }
}
public class B extends A{ public String show(B obj){ return ("B and B"); } public String show(A obj){ return ("B and A"); } }
public class C extends B{
}
public class D extends B{
}
public class Test { public static void main(String[] args) { A a1 = new A(); A a2 = new B(); B b = new B(); C c = new C(); D d = new D(); System.out.println("1--" + a1.show(b)); System.out.println("2--" + a1.show(c)); System.out.println("3--" + a1.show(d)); System.out.println("4--" + a2.show(b)); System.out.println("5--" + a2.show(c)); System.out.println("6--" + a2.show(d)); System.out.println("7--" + b.show(b)); System.out.println("8--" + b.show(c)); System.out.println("9--" + b.show(d)); } }
|
上每A,B,C类都有一个show方法。如果我们执行上面代码,会发现输出的结果会由于创建的类不同而不同。
1 2 3 4 5 6 7 8 9
| 1--A and A 2--A and A 3--A and D 4--B and A 5--B and A 6--A and D 7--B and B 8--B and B 9--A and D
|
但是第四行为什么输出的不是“B AND B”呢。因为a2调用show方法的对象的静态类型是A,其次静态类型的参数是B。在A类中最匹配的方法是 public String show(A obj)。但是如果调用了A类的该方法,那么输出应该是”A and A”。 所以另一个原因是,我们可以在B类中找到一个更加具体的方法。更具体的方法的定义:function(type1_1 p1, …, type1_n pn)比function(type2_1 p2, …, type2_n pn)更加具体,当且仅当对有所有的i,1$\leqslant$i$\leqslant$n,type1_i是type2_i的子类。
在上面这种静态类型和动态类型不一致的情况下,编译器会对静态类型的类里面的方法进行以下检索:
- 检查在静态类型的类中是否有该函数
- 检测是否有多个签名匹配(子类是否重写该方法)
- 返回最具体最匹配的方法
如果静态类型和动态类型一致,那么就会有以下的调用顺序:this.show(O)、super.show(O)、this.show((super)O)、super.show((super)O)。
总结
多态的最重要的条件是方法的重写,而重写又离不开继承。所以要实现多态必定有继承和重写这两个技术。
如果发现错误请留言告知,万分感谢。
参考资料