知道java里绑定的所有方法都通过后期绑定具有多形性以后,就可以相应地编写自己的代码,令其与基础类沟通。此时,所有的衍生类都保证能用相同的代码正常地工作。或者换用另一种方法,我们可以“将一条消息发给一个对象,让对象自行判断要做什么事情。

在面向对象的程序设计中,有一个经典的“形状”例子。由于它很容易用可视化的形式表现出来,所以经常都用它说明问题。但很不幸的是,它可能误导初学者认为OOP只是为图形化编程设计的,这种认识当然是错误的。

形状例子有一个基础类,名为Shape;另外还有大量衍生类型:Circle(圆形),Square(方形),Triangle(三角形)等等。大家之所以喜欢这个例子,因为很容易理解“圆属于形状的一种类型”等概念。下面这幅继承图向我们展示了它们的关系:

上溯造型可用下面这个语句简单地表现出来:

Shape s = new Circle();

在这里,我们创建了Circle对象,并将结果句柄立即赋给一个Shape。这表面看起来似乎属于错误操作(将一种类型分配给另一个),但实际是完全可行的——因为按照继承关系,Circle属于Shape的一种。因此编译器认可上述语句,不会向我们提示一条出错消息。

当我们调用其中一个基础类方法时(已在衍生类里覆盖):

s.draw();

同样地,大家也许认为会调用Shape的draw(),因为这毕竟是一个Shape句柄。那么编译器怎样才能知道该做其他任何事情呢?但此时实际调用的是Circle.draw(),因为后期绑定已经介入(多形性)。

下面这个例子从一个稍微不同的角度说明了问题:

//: Shapes.java

// Polymorphism in Java

class Shape {

void draw() {}

void erase() {}

}

class Circle extends Shape {

void draw() {

System.out.println("Circle.draw()");

}

void erase() {

System.out.println("Circle.erase()");

}

}

class Square extends Shape {

void draw() {

System.out.println("Square.draw()");

}

void erase() {

System.out.println("Square.erase()");

}

}

class Triangle extends Shape {

void draw() {

System.out.println("Triangle.draw()");

}

void erase() {

System.out.println("Triangle.erase()");

}

}

public class Shapes {

public static Shape randShape() {

switch((int)(Math.random() * 3)) {

default: // To quiet the compiler

case 0: return new Circle();

case 1: return new Square();

case 2: return new Triangle();

}

}

public static void main(String[] args) {

Shape[] s = new Shape[9];

// Fill up the array with shapes:

for(int i = 0; i < s.length; i++)

s[i] = randShape();

// Make polymorphic method calls:

for(int i = 0; i < s.length; i++)

s[i].draw();

}

} ///:~

针对从Shape衍生出来的所有东西,Shape建立了一个通用接口——也就是说,所有(几何)形状都可以描绘和删除。衍生类覆盖了这些定义,为每种特殊类型的几何形状都提供了独一无二的行为。

在主类Shapes里,包含了一个static方法,名为randShape()。它的作用是在每次调用它时为某个随机选择的Shape对象生成一个句柄。请注意上溯造型是在每个return语句里发生的。这个语句取得指向一个Circle,Square或者Triangle的句柄,并将其作为返回类型Shape发给方法。所以无论什么时候调用这个方法,就绝对没机会了解它的具体类型到底是什么,因为肯定会获得一个单纯的Shape句柄。

main()包含了Shape句柄的一个数组,其中的数据通过对randShape()的调用填入。在这个时候,我们知道自己拥有Shape,但不知除此之外任何具体的情况(编译器同样不知)。然而,当我们在这个数组里步进,并为每个元素调用draw()的时候,与各类型有关的正确行为会魔术般地发生,就象下面这个输出示例展示的那样:

Circle.draw()

Triangle.draw()

Circle.draw()

Circle.draw()

Circle.draw()

Square.draw()

Triangle.draw()

Square.draw()

Square.draw()

当然,由于几何形状是每次随机选择的,所以每次运行都可能有不同的结果。之所以要突出形状的随机选择,是为了让大家深刻体会这一点:为了在编译的时候发出正确的调用,编译器毋需获得任何特殊的情报。对draw()的所有调用都是通过动态绑定进行的。

java语言产生_在java语言中产生正确的行为相关推荐

  1. c语言和java哪个好学_学java前要学C语言吗?java和C语言哪个好学?

    在编程世界,只要一提到java,总会有人联想到C语言,仿佛这两者之间有着一种密不可分的联系,那么也会有外行人在选择学习编程时,会有类似于学java前是否需要学习C语言呢?或者说java和C语言哪个会比 ...

  2. java是脚本语言吗_从脚本语言到Java

    从脚本语言到Java 板桥里人 jdon.com 2002/3 以前我是一直用脚本语言,使用多了,不知不觉一直把数据库设计当作系统设计的主要任务,使用java后,我觉得数据库设计只是一个基础 和前期工 ...

  3. java语言情话_用Java怎么编一段情话

    java书上的一段话 方法一:直接打印一段话:System.out.println( 我在高三1班上计算机课);方法二:定义班级和课程:String classRoom = 高三一班, subject ...

  4. java skip函数_【Java必修课】图说Stream中的skip()和limit()方法及组合使用

    1 简介 本文将讲解Java 8 Stream中的两个方法:skip()和limit().这两个方法是Stream很常用的,不仅各自会被高频使用,还可以组合出现,并能实现一些小功能,如subList和 ...

  5. java递归优化_在Java中谈尾递归--尾递归和垃圾回收的比较

    我不是故意在JAVA中谈尾递归的,因为在JAVA中谈尾递归真的是要绕好几个弯,只是我确实只有JAVA学得比较好,虽然确实C是在学校学过还考了90+,真学得没自学的JAVA好 不过也是因为要绕几个弯,所 ...

  6. java协程_在Java中使用协程(Coroutine)

    各种语言在实现Coroutine方式的支持时,多数都采用了Actor Model来实现,Actor Model简单来说就是每个任务就是一个Actor,Actor之间通过消息传递的方式来进行交互,而不采 ...

  7. Java main方法_解释Java中的main方法,及其作用_一个java文件中可包含多个main方法

    public static void main(String[] args) {} 或者 public static void main(String args[]) {} main方法是我们学习Ja ...

  8. java jar 目录_将Java类路径中的所有jar包括在一个目录中

    有没有一种方法可以将所有的jar文件包含在类路径的目录中? 我正在尝试java -classpath lib / *.jar :. my.package.Program,它无法找到当然在这些罐子里的类 ...

  9. java避免空指针异常_避免Java中的空指针异常

    java避免空指针异常 空指针异常是Java中最常见,最烦人的异常. 在这篇文章中,我想避免这种不希望的异常. 首先让我们创建引发空指针异常的示例 private Boolean isFinished ...

  10. java字符串数组排序_在Java中对字符串数组进行排序

    允许用户使用字符串数组.他们可以向数组添加字符串,从数组中删除字符串,搜索数组中的字符串,最终他们将能够对数组进行排序.分类是搞砸我的原因.我尝试过几种不同的方法.第一种方法是将数组转换为ArrayL ...

最新文章

  1. Spring微服务视频免费发放
  2. python批量合并csv_Python合并多个csv文件
  3. VC/MFC中常用宏的含义
  4. Excel 2007中创建或删除自定义数字格式
  5. python装饰器有几种_python几种装饰器的用法
  6. Python3 字符串拼接
  7. python 使用标准库连接linux实现scp和执行命令
  8. c study_13
  9. Linux查看硬件信息命令大全
  10. IT笔试题收集,免费下载
  11. DCMM讲的数据“需求管理”,是什么?管理目标?如何实现?
  12. html 原始数据类型,JS原始数据类型-String
  13. 购袖珍电子计算机笔记本,购买迷你电脑,哪个品牌值得信赖
  14. 财路网每日原创推送:区块链+教育,是改革的良性循环?
  15. shell 脚本批量检测主机存活状态
  16. JavaFX实现学生成绩管理系统(综合实践大作业)
  17. Java输出BMI体重指数
  18. AVR ATMEGA8的初次使用
  19. 【基础】电动势、电位、电压、电压降
  20. 辛苦找了十个高质量的前端公众号来分享给大家~

热门文章

  1. raise BrowserError pyppeteer.errors.BrowserError: Browser closed unexpectedly(服务器是fedora)
  2. 中国首创新一代交流LED白光照明光源技术
  3. 网络性能监测工具smokeping
  4. Linux系统安装 Centos6.8系统安装详细教程
  5. HDU 1914 The Stable Marriage Problem (稳定婚姻匹配)
  6. 港科夜闻丨香港科大校长加入“一群关注社会现况的大学校长之声明”
  7. Tomcat设置SSO后报告错误 Defective token detected
  8. #include 中 和 的区别
  9. 【CMAC小脑网络】基于CMAC的目标分类matlab仿真
  10. minimal linux图形化,CentOS7 Minimal 最小化安装后再安装GNOME图形界面