见:重载
见:继承
封装和继承是为多态准备的。你准备好了吗?
定义:指允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。(发送消息就是函数调用)
实现多态的技术称为:动态绑定(dynamic binding),是指在执行期间判断所引用对象的实际类型,根据其实际的类型调用其相应的方法。
多态的作用:消除类型之间的耦合关系。
父类引用指向子类对象。
可替换性
可扩充性
接口性
灵活性
简化性
- class A {
- public String show(D obj) {
- return ("A and D");
- }
- public String show(A obj) {
- return ("A and A");
- }
- }
- class B extends A{
- public String show(B obj){
- return ("B and B");
- }
- public String show(A obj){
- return ("B and A");
- }
- }
- class C extends B{
- }
- 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));
- }
- }
运行结果:
- 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
注意:一个文件中只能有一个 public 类。
第一组:1,2,3:类实例化的类型是父类 A,输入的参数是三个子类,调用的父类的方法,执行输出的就是父类自己的方法结果。
第二组:4,5,6:类实例化的类型是子类 B,输入的参数是三个子类,调用的方法应是子类的方法。按这个思路下去,输出的应是 B 类中的方法值“
B and B”和“
B and A”
那结果为什么没有“
B and B”?
Java实现运行时多态性的基础是动态方法调度,它是一种在运行时而不是在编译期调用重载方法的机制。
实际上这里涉及方法调用的优先问题 ,优先级由高到低依次为:this.show(O)、super.show(O)、this.show((super)O)、super.show((super)O)。让我们来看看它是怎么工作的。
从上面的程序中我们可以看出A、B、C、D存在如下关系。
首先我们分析 5,a2.show(c),a2是A类型的引用变量,所以this就代表了A,
第一级:a2.show(c),它在A类中找发现没有找到,
第二级:于是到A的超类中找(super),由于A没有超类(Object除外),
所以跳到第三级:也就是this.show((super)O),C的超类有B、A,所以(super)O为B、A,this同样是A,这里在A中找到了show(A obj),同时由于a2是B类的一个引用且B类重写了show(A obj),因此最终会调用子类B类的show(A obj)方法,结果也就是B and A。
再分析一下 6,a2.show(d),a2 是 A 类型的引用变量,所以 this 就代表了 A。
第一级:于是到 A 类中查找参数为 C 的方法。就找到了输出
A and D
所以多态机制遵循的原则概括为:
当超类对象引用变量引用子类对象时,被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法,但是这个被调用的方法必须是在超类中定义过的,也就是说被子类覆盖的方法,但是它仍然要根据继承链中方法调用的优先级来确认方法,该优先级为:this.show(O)、super.show(O)、this.show((super)O)、super.show((super)O)。