码迷,mamicode.com
首页 > 编程语言 > 详细

java 多态与动态绑定的理解

时间:2016-04-08 18:14:08      阅读:217      评论:0      收藏:0      [点我收藏+]

标签:

先来一段百度来的定义和概念

什么是多态:
面向对象的三大特性:封装、继承、多态。从一定角度来看,封装和继承几乎都是为多态而准备的。这是我们最后一个概念,也是最重要的知识点。
多态的定义:指允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。(发送消息就是函数调用)
实现多态的技术称为:动态绑定(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...{}


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));    ⑨
Answer:
①   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

上述的概念似乎并不清楚,并且也无助于理解多态这样一个概念。结尾我们将进行上述问题的详细解析。

进行下述实践:

Parent aParent = new Child();

aParent在进行动态绑定时的方法匹配范围为Parent Class中未被Child Class覆盖的method,以及Child Class中override的所有方法。Child Class中所有不包含在Parent Class中的方法在向上转型的时候会全部被除去(实际上也不可能出现这种情况,加入method在Parent中不存在的话,aParent.method()是无法通过编译的,更谈何执行)。

ps:可以形象的认为此处aParent作为Child的实例进行了向上类型转换(Parent), 除去了Parent Class中未定义的方法,并对Parent Class中的方法进行了override。

此时多态的特性主要体现在Child Class中重写过的方法:

Class Parent{
....
  override_method(){
 }
....
}

 

class Child extends Parent....{
....
  overrride_method(){
    System.out.print("I‘m child.")
  }
...
}

class Nephew extends Parent....{
....
  overrride_method(){
    System.out.print("I‘m nephew.")
  }
...
}

 

Parent aParent = new Child();
Parent bParent = new Nephew();
aParent.override_method();
bParent.override_method();

OUTPUT:
I‘m child.
I‘m nephew.

 在Parent的引用下调用同一个方法,不同的子类实例就会产生不同的方法表现,是比较直观的多态体现。

再一步深入该过程的细节:

1.在方法调用时发生了什么?

按照搜索结果,我们可以得知,override_method的调用过程体现了动态绑定的概念。

首先引入方法签名的概念:

即一个对象的方法定义唯一辨识包含两部分:方法名和参数列表。它们共同组成一个方法的唯一标识。

overload:同一个类中方法名相同,但是参数列表不同的方法定义称为方法重载(overload)

override: 与超类中的方法名,参数列表完全相同的子类中的方法定义称为覆盖(override)

ps: 如果子类中的方法定义仅仅是方法名与超类中的方法相同,则并不会覆盖超类中的方法实现。其效果类似于方法重载的结果。

2.对象方法的执行过程:

1.假设x声明为C类的对象,即C x = new C(); 调用x.f(参数p),那么编译器将会一一列举所有C类中名为f的方法和C的超类中访问属性为public且名为f且未被C中的f覆盖的方法。

2.接下来,编译器进行调用方法时提供的参数列表的检查,如果所有名为f的方法中存在完全匹配的参数类型,那么就选择这个方法,这个过程称为重载解析,然而可能存在并没有完全匹配的参数类型的情况,编译器将对传入的参数进行类型转换,如int可以转成double,子类转成父类(此行为将会检索整个向上的继承链)。如果进行转换后没有匹配的,或者发现经过转换后有多个方法与之匹配,则会发生错误。

3.采用动态绑定调用方法时,虚拟机一定调用的是x所引用对象的实际类型最合适的那个类的方法。举个栗子:Class D extends C, C x = new D(); 进行x.f(String)调用,那么首先如果D中定义了f(String)那么直接调用D中的f(String),如果D中没有定义,那么将在超类C中寻找f(String),如果还没有找到,依次类推向上搜索整个继承链。

4.有动态绑定,那么对应的就有静态绑定:所有private、static、final方法或者constructor方法都是编译器能够准确知道调用的是哪一个方法,称之为static binding。

接下来我们看一下开头那个问题:

1.a1.show(b)

声明引用的类型为A,实际对象类型也是A,参数列表为 B 类型,包含show方法为show(D),show(A),此时没有完全匹配调用show(B)的,进行传入参数的类型向上转换,B的超类为A,传入参数列表中的B转换为A,匹配show(A),调用show(A)

返回A and A。

2.a1.show(c)

声明引用的类型为A,实际对象类型也是A,参数列表为 C 类型,包含show方法为show(D),show(A),此时没有完全匹配调用show(C)的,进行传入参数的类型向上转换,C的超类为B,B并无匹配项,继续向上转换得到A,传入参数列表中的B转换为A,匹配show(A),调用show(A).

返回A and A

3.a1.show(d)

同上。

返回A and A。

4.a2.show(b)

声明引用为A类型,实际实例类型为B,调用的方法为show(B),首先我们来看A中的show,show(D),show(A),在看B中的show(B),show(A)其中show(A)override了A中的show(A),show(B)方法在A中不存在,排除。所以备选为A.show(D),B.show(A),传入参数B向上转换成A,匹配B.show(A)

返回B and A

5.a2.show(c)

同上

6.a2.show(d)

声明引用为A类型,实际实例类型为B,调用的方法为show(B),首先我们来看A中的show,show(D),show(A),在看B中的show(B),show(A)其中show(A)override了A中的show(A),show(B)方法在A中不存在,排除。所以备选为A.show(D),B.show(A),匹配A.show(D)

返回A and D

7.b.show(b)

声明引用为B,实际类型为b,调用的方法为show(B),直接调用B.show(B)

返回B and B。

8.b.show(c)

声明引用为B,实际类型为b,调用的方法为show(C),B和超类A中无方法匹配,C向上转换为B,匹配B.show(B)

返回B and B

9.b.show(d)

声明引用为B,实际类型为b,调用的方法为show(D),B中方法无匹配,但B的超类A中匹配方法a.show(D)

返回A and D

java 多态与动态绑定的理解

标签:

原文地址:http://www.cnblogs.com/coonver/p/5368683.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!