多态

多态

多态是指对不同的子类调用相同的方法,输出的结果不同。意思是程序在编译的时候并不知道要调用哪个类的方法,必须等到程序运行的时候才能决定。

对象多态类型

对象的多态类型一共有两种:静态类型,动态类型。静态类型是对类而言,在程序运行的过程为中,静态类型的类会根据引用对象的改变而改变。动态类型对对象而言,一但一个对象被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的子类。

在上面这种静态类型和动态类型不一致的情况下,编译器会对静态类型的类里面的方法进行以下检索:

  1. 检查在静态类型的类中是否有该函数
  2. 检测是否有多个签名匹配(子类是否重写该方法)
  3. 返回最具体最匹配的方法

如果静态类型和动态类型一致,那么就会有以下的调用顺序:this.show(O)、super.show(O)、this.show((super)O)、super.show((super)O)。

总结

多态的最重要的条件是方法的重写,而重写又离不开继承。所以要实现多态必定有继承重写这两个技术。

如果发现错误请留言告知,万分感谢。

参考资料


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!