服务热线:13616026886

技术文档 欢迎使用技术文档,我们为你提供从新手到专业开发者的所有资源,你也可以通过它日益精进

位置:首页 > 技术文档 > JAVA > 新手入门 > 基础入门 > 查看文档

品味java子类型多态的魅力

ad_qqread_mid_big">面向类型观点

  图1的uml类图给出了类和类型的简单继承关系,以便于解释多态机制。模型中包含5种类型,4个类和一个接口。虽然uml中称为类图,我把它看成类型图。如"thanks type and gentle class," 一文中所述,每个类和接口都是一种用户定义的类型。按独立实现的观点(如面向类型的观点),下图中的每个矩形代表一种类型。从实现方法看,四种类型运用了类的结构,一种运用了接口的结构。

品味java子类型多态的魅力(图二)
图1:示范代码的uml类图

  以下的代码实现了每个用户定义的数据类型,我把实现写得很简单。

/* base.java */

public class base
{
 public string m1()
 {
  return "base.m1()";
 }

 public string m2( string s )
 {
  return "base.m2( " + s + " )";
 }
}

/* itype.java */

interface itype
{
 string m2( string s );
 string m3();
}

/* derived.java */

public class derived
extends base
implements itype
{
 public string m1()
 {
  return "derived.m1()";
 }

 public string m3()
 {
  return "derived.m3()";
 }
}

/* derived2.java */

public class derived2
extends derived
{
 public string m2( string s )
 {
  return "derived2.m2( " + s + " )";
 }
 public string m4()
 {
  return "derived2.m4()";
 }
}

/* separate.java */

public class separate
implements itype
{
 public string m1()
 {
  return "separate.m1()";
 }
 public string m2( string s )
 {
  return "separate.m2( " + s + " )";
 }

 public string m3()
 {
  return "separate.m3()";
 }
}

  用这样的类型声明和类的定义,图2从概念的观点描述了java指令。

derived2 derived2 = new derived2();

品味java子类型多态的魅力(图三)
图2 :derived2 对象上的引用

  上文中声明了derived2这个对象,它是derived2类的。图2种的最顶层把derived2引用描述成一个集合的窗口,虽然其下的derived2对象是可见的。这里为每个derived2类型的操作留了一个孔。derived2对象的每个操作都去映射适当的代码,按照上面的代码所描述的那样。例如,derived2对象映射了在derived中定义的m1()方法。而且还重载了base类的m1()方法。一个derived2的引用变量无权访问base类中被重载的m1()方法。但这并不意味着不可以用super.m1()的方法调用去使用这个方法。关系到derived2这个引用的变量,这个代码是不合适的。derived2的其他的操作映射同样表明了每种类型操作的代码执行。

  既然你有一个derived2对象,可以用任何一个derived2类型的变量去引用它。如图1所示,derived, base和itype都是derived2的基类。所以,base类的引用是很有用的。图3描述了以下语句的概念观点。

base base = derived2;

品味java子类型多态的魅力(图四)
图3:base类引用附于derived2对象之上
 
  虽然base类的引用不用再访问m3()和m4(),但是却不会改变它derived2对象的任何特征及操作映射。无论是变量derived2还是base,其调用m1()或m2(string)所执行的代码都是一样的。

string tmp;
// derived2 reference (figure 2)
tmp = derived2.m1(); // tmp is "derived.m1()"
tmp = derived2.m2( "hello" ); // tmp is "derived2.m2( hello )"

// base reference (figure 3)

tmp = base.m1(); // tmp is "derived.m1()"
tmp = base.m2( "hello" ); // tmp is "derived2.m2( hello )"

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

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

string tmp;
// derived2 reference (figure 2)
tmp = derived2.m3(); // tmp is "derived.m3()"
tmp = derived2.m4(); // tmp is "derived2.m4()"

// base reference (figure 3)

tmp = base.m3(); // compile-time error
tmp = base.m4(); // compile-time error

  运行期的derived2对象保持了接受m3()和m4()方法的能力。类型的限制使base的引用不能在编译期调用这些方法。编译期的类型检查像一套铠甲,保证了运行期对象只能和正确的操作进行相互作用。换句话说,类型定义了对象间相互作用的边界。 >>>更多专题请看java的类专题
上一页 1 2 3 4 5 下一页 
相关内容:效果  设计  技巧  java  
【收藏此页】【大 中 小】【打印】【关闭】
上一篇:利用des加密算法保护java源代码
下一篇:java实现的18位身份证格式验证算法


10万个软件免费高速下载
教育教学 安全相关 游戏娱乐 源码下载 编程开发 数码软件 其它类别
网络软件 联络聊天 系统工具 媒体工具 图形图像 应用软件 行业软件
·java: jni完全手册
·java reflection (java反射)详解
·java连接数据库谈
·深入java字节码加密
·java虚拟机类装载:原理、实现与应用
·java反编译的研究
·jsp与java mail api
·让界面更加绚丽 java se 6.0 gui体验
·为什么是java ee 5
·使用java 输出/输出流读写数据
 
·接口和抽象类的定义方式举例说明
·用maven制作java项目发行包
·java 基础入门 pom.xml 元素描述
·用jbuilder2007开发扩展jsf标签的插
·抽象类对象类和对象包装类
·使用java实现在文件中添加字符串
·instanceof和回调概念
·java变量的赋值与传递
·java se6调用java编译器的两种新方法
·weblogic运用db的java控件访问数据库

扫描关注微信公众号