Java中多态性(polymorphism)的实现
什么是多态
1、 面向对象的三大特性:封装、继承、多态。从一定角度来看,封装和继承几乎都是为多态而准备的。这是我们最后一个概念,也是最重要的知识点。
多态的定义:指允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。(发送消息就是函数调用)
实现多态的技术称为:动态绑定(dynamic binding),是指在执行期间判断所引用对象的实际类型,根据其实际的类型调用其相应的方法。
多态的作用:消除类型之间的耦合关系。
多态的实现条件:
继承、重写、父类引用指向子类对象。
网络上面常见的对多态的理解:
多态性有两种:
1)编译时多态性
对于多个同名方法,如果在编译时能够确定执行同名方法中的哪一个,则称为编译时多态性.
2)运行时多态性
如果在编译时不能确定,只能在运行时才能确定执行多个同名方法中的哪一个,则称为运行时多态性.
上面的划分方法个人不敢苟同。---编译期的方法重载不应该称之为多态,这种方法重载是在编译期已经确定的事情,不具备动态性,多态是针对程序员而言的,而不是程序,多态是可扩展的(在不改变原码的基础上,实现更好的扩展)。所以就像上面所说,动态绑定(Dynamic Binding)--在运行期来决定要做什么,而不是在编译期。Runtime polymorphism (dynamic binding or method overriding)。
多态的好处:
更高的可扩展性。降低了耦合性。
多态的经典实例:
(一)相关类
1 class A ...{ 2 public String show(D obj)...{ 3 return ("A and D"); 4 } 5 public String show(A obj)...{ 6 return ("A and A"); 7 } 8 } 9 class B extends A...{ 10 public String show(B obj)...{ 11 return ("B and B"); 12 } 13 public String show(A obj)...{ 14 return ("B and A"); 15 } 16 } 17 class C extends B...{} 18 class D extends B...{}
测试:
A a1 = new A(); A a2 = new B(); B b = new B(); C c = new C(); D d = new D(); System.out.println(a1.show(b)); ① System.out.println(a1.show(c)); ② System.out.println(a1.show(d)); ③ System.out.println(a2.show(b)); ④ System.out.println(a2.show(c)); ⑤ System.out.println(a2.show(d)); ⑥ System.out.println(b.show(b)); ⑦ System.out.println(b.show(c)); ⑧ System.out.println(b.show(d)); ⑨
答案:
① A and A ② A and A ③ A and D ④ B and A ⑤ B and A ⑥ A and D ⑦ B and B ⑧ B and B ⑨ A and D
解析:
----->当父类对象引用变量引用子类对象时,被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法,但是这个被调用的方法必须是在超类中定义过的,也就是说被子类覆盖的方法。(但是如果强制把超类转换成子类的话,就可以调用子类中新添加而超类没有的方法了。)
+--->上面的这句话比较重要,两层意思++
看第④个 a2.show(b), a2是一个引用变量,类型为A,它引用的是B的一个对象,因此这句话的意思是由B来决定调用的是哪个方法。因此应该调用B的show(B obj)从而输出"B and B”才对。但是为什么跟前面的分析得到的结果不相符呢?!问题在于我们不要忽略了上面红色字体的部分,那里特别指明:这个被调用的方法必须是在超类中定义 过的,也就是被子类覆盖的方法。B里面的show(B obj)在超类A中有定义吗?没有!那就更谈不上被覆盖了。
实际上,在多态中涉及方法调用的优先问题 ,优先级由高到低依次为:
this.show(O) ----> super.show(O) ---> this.show((super)O) ---> super.show((super)O)。
这种优先级是建立在满足上面条件的基础上。