深入Java核心 Java中多态的实现机制

发表于:2010-9-19 10:58

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:zl198751(JavaEye博客    来源:51Testing软件测试网采编

  两个引用之所以调用同一个行为,是因为Derived2对象并不知道去调用哪个方法。对 象只知道什么时候调用,它随着继承实现的顺序去执行。这样的顺序决定了Derived2对象调用Derived里的m1()方法,并调用Derived2 里的m2(String)方法。这种结果取决于对象本身的类型,而不是引用的类型。

  尽管如此,但不意味着你用derived2和 base引用的效果是完全一样的。如图3所示,Base的引用只能看到Base类型拥有的操作。所以,虽然Derived2有对方法m3()和m4()的 映射,但是变量base不能访问这些方法。

  运行期的Derived2对象保持了接受m3()和m4()方法的能力。类型的限制使 Base的引用不能在编译期调用这些方法。编译期的类型检查像一套铠甲,保证了运行期对象只能和正确的操作进行相互作用。换句话说,类型定义了对象间相互 作用的边界。

  多态的依附性

  类型的一致性是多态的核心。对象上的每一个引用,静态的类型检查器都要确认这样的依附和其对象的层次是一致的。当一个引用成功的依附于另一个不同的对象 时,有趣的多态现象就产生了。(严格的说,对象类型是指类的定义。)你也可以把几个不同的引用依附于同一个对象。在开始更有趣的场景前,我们先来看一下下 面的情况为什么不会产生多态。

  多个引用依附于一个对象

  图2和图3描述的例子是把两个及两个以上的 引用依附于一个对象。虽然Derived2对象在被依附之后仍保持了变量的类型,但是,图3中的Base类型的引用依附之后,其功能减少了。结论很明显: 把一个基类的引用依附于派生类的对象之上会减少其能力。

  一个开发这怎么会选择减少对象能力的方案呢?这种选择是间接的。假设有一个名 为ref的引用依附于一个包含如下方法的类的对象:

  用一个Derived2的参数调用poly(Base)是符合参数类型检查的:

  方法调用把一个本地Base类型的变量依附在一个引入的对象上。所以,虽然这个方法只接 受Base类型的参数,但Derived2对象仍是允许的。开发这就不必选择丢失功能的方案。从人眼在通过Derived2对象时所看到的情况,Base 类型引用的依附导致了功能的丧失。但从执行的观点看,每一个传入poly1(Base)的参数都认为是Base的对象。执行机并不在乎有多个引用指向同一 个对象,它只注重把指向另一个对象的引用传给方法。这些对象的类型不一致并不是主要问题。执行器只关心给运行时的对象找到适当的实现。面向类型的观点展示 了多态的巨大能力。

  附于多个对象的引用

  让我们来看一下发生在poly1(Base)中的多态行 为。下面的代码创建了三个对象,并通过引用传给poly1(Base):

  poly1(Base)的实现代码是调用传进来的参数的m1()方法。图3和图4展示了 把三个类的对象传给方法时,面向类型的所使用的体系结构。

图4:将Base引用指向Derived类,以及Base对象

  请注意每个图中方法m1()的映射。图3中,m1()调用了Derived类的代码;上面代码中的注释标明了ploy1(Base)调用 Derived.m1()。图4中Derived对象调用的仍然是Derived类的m1()方法。最后,图4中,Base对象调用的m1()是Base 类中定义的代码。

  多态的魅力何在?再来看一下poly1(Base)的代码,它可以接受任何属于Base类范畴的参数。然而,当他收 到一个Derived2的对象时,它实际上却调用了Derived版本的方法。当你根据Base类派生出其他类时,如 Derived,Derived2,poly1(Base)都可以接受这些参数,并作出选择调用合适的方法。多态允许你在完成poly1(Base)后扩 展它的用途。

  这看起来当然很神奇。基本的理解展示了多态的内部工作原理。在面向类型的观点中,底层的对象所实现的代码是非实质性的。 重要的是,类型检查器会在编译期间为每个引用选择合适的代码以实现其方法。多态使开发者运用面向类型的观点,不考虑实现的细节。这样有助于把类型和实现分 离(实际用处是把接口和实现分离)。

  对象接口

  多态依赖于类型和实现的分离,多用来把接口和实现分离。但下面的观点好像把Java的关键字 interface搞得很糊涂。

  更为重要的使开发者们怎样理解短语“the interface to an object",典型地,根据上下文,这个短语的意思是指一切对象类中所定义的方法,至一切对象公开的方法。这种倾向于以实现为中心的观点较之于面向类型 的观点来说,使我们更加注重于对象在运行期的能力。图3中,引用面板的对象表面被标志成"Derived2 Object"。这个面板上列出了Derived2对象的所有可用的方法。但是要理解多态,我们必须从实现这一层次上解放出来,并注意面向类型的透视图中 被标为"Base Reference"的面板。在这一层意思上,引用变量的类型指明了一个对象的表面。这只是一个表面,不是接口。在类型一致的原则下,我们可以用面向类型 的观点,为一个对象依附多个引用。对interface to an object这个短语的理解没有确定的理解。

54/5<12345>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号