上溯造型

之所以叫作上溯造型,除了有一定的历史原因外,也是由于在传统意义上,类继承图的画法是根位于最顶部,再逐渐向下扩展
由于造型的方向是从衍生类到基础类,箭头朝上,所以通常把它叫作“上溯造型”,即Upcasting。上溯造型肯定是安全的,因为我们是从一个更特殊的类型到一个更常规的类型。换言之,衍生类是基础类的一个超集。它可以包含比基础类更多的方法,但它至少包含了基础类的方法。进行上溯造型的时候,类接口可能出现的唯一一个问题是它可能丢失方法,而不是赢得这些方法。这便是在没有任何明确的造型或者其他特殊标注的情况下,编译器为什么允许上溯造型的原因所在。

//: Wind.java
// Inheritance & upcasting
import java.util.*;class Instrument {public void play() {}static void tune(Instrument i) {// ...i.play();}
}// Wind objects are instruments
// because they have the same interface:
class Wind extends Instrument {public static void main(String[] args) {Wind flute = new Wind();Instrument.tune(flute); // Upcasting}
} ///:~

这个例子中最有趣的无疑是tune()方法,它能接受一个Instrument句柄。但在Wind.main()中,tune()方法是通过为其赋予一个Wind句柄来调用的。由于Java对类型检查特别严格,所以大家可能会感到很奇怪,为什么接收一种类型的方法也能接收另一种类型呢?但是,我们一定要认识到一个Wind对象也是一个Instrument对象。而且对于不在Wind中的一个Instrument(乐器),没有方法可以由tune()调用。在tune()中,代码适用于Instrument以及从Instrument衍生出来的任何东西。在这里,我们将从一个Wind句柄转换成一个Instrument句柄的行为叫作“上溯造型”。

取得一个对象句柄,并将其作为基础类型句柄使用的行为就叫作“上溯造型”。

为什么要上溯造型?
假如只写一个方法,不使用特定的衍生类,而是将基础类作为自变量或参数使用,会简单很多。也就是说,如果能不顾衍生类,只让代码与基础类打交道,那么省下的工作量将是难以估计的。

方法调用绑定(Method-call binding)

将方法调用同方法主体连接起来称为“绑定”(Binding)。
若在程序运行之前执行绑定(由编译器和链接程序执行,如果有的话),则称作“早期绑定”(early binding)。
当程序只有基础类的句柄时,编译器不知道调用哪个方法是正确的。后期绑定(late binding)能够解决这个问题。后期绑定也叫作“动态绑定”(dynamic binding)或“运行期绑定”(runtime binding),指的是根据对象的类型在运行期间(runtime)进行绑定

实现了后期绑定的语言,必须提供一种机制,即在运行期间判断对象的类型,然后调用相应的方法。也就是说,编译器此时还是不知道对象的类型,但方法调用机制(method-call binding)会去找到并调用正确的方法主体。不同的语言对后期绑定的实现方法各有区别。但是可以设想,它们都必须在对象中安插某些特殊类型的信息。

Java中绑定的所有方法都采用后期绑定,除非一个方法已被声明成static或final(private方法是隐式的final)。开发者不必决定是否应进行后期绑定——后期绑定是自动发生的。

上溯造型的具体实现

Java里所有绑定的方法通过后期绑定具有多态性后,就可以相应地编写自己的代码,并使其和基础类沟通。

在此以Shape举例:
Shape为基类;Circle(圆形),Square(方形),Triangle(三角形)等等是衍生类:

上塑造型语句:
Shape s = new Circle();
我们创建了Circle对象,并将结果句柄立即赋给一个Shape。这表面看起来似乎属于错误操作(将一种类型分配给另一个),但实际是完全可行的——因为按照继承关系,Circle属于Shape的一种。因此编译器认可上述语句,不会向我们提示一条出错消息。
当我们调用其中一个基础类方法时(已在衍生类里覆盖):
s.draw();
调用已在Circle中重写过的draw()方法,注意Shape中也有同名的draw()方法
s.draw() 调用的是Circle中的draw()方法

//: Shapes.java
// Polymorphism in Javaclass 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 compilercase 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();}
} ///:~

【JAVA】 多态-上溯造型相关推荐

  1. Java 的上溯造型和下溯造型以及举例,以及判断参数等指向的类

    (一) 先给出个例子,代码如下: /** * @author WangQun * 动物抽象类 */ abstract class Animal { public abstract void speak ...

  2. java上溯造型与下溯造型

    Java的多态性 面向对象编程有三个特征,即封装.继承和多态. 封装隐藏了类的内部实现机制,从而可以在不影响使用者的前提下改变类的内部结构,同时保护了数据. 继承是为了重用父类代码,同时为实现多态性作 ...

  3. 封装、权限修饰符、javaBean规范、继承中封装、多态、关于上溯造型的解释。

    一.封装 类 .方法.属性这些java中编程所涉及到的元素的访问权限控制 二.权限修饰符 修饰成员 public      protected      default     private 本类中 ...

  4. java 上溯_java中Instrument的上溯造型

    继承最值得注意的地方就是它没有为新类提供方法.继承是对新类和基础类之间的关系的一种表达.可这样总结该关系:"新类属于现有类的一种类型". 这种表达并不仅仅是对继承的一种形象化解释, ...

  5. [Java初学]Java上溯造型(upcasting)与下溯造型(Downcasting)

    Java上溯造型(upcasting)与下溯造型(Downcasting) 上溯造型(upcasting) 这个术语缘于继承关系图的传统画法:将基类至于顶部,而向下发展的就是派生类. 文章使用的完整代 ...

  6. Java——上溯造型下溯造型

    public abstract class Animal {public abstract void speak();public void eat(){// 吃吃吃!!! } } public in ...

  7. java 下溯造型_Java——上溯造型下溯造型

    public abstract class Animal { public abstract void speak(); public void eat(){ // 吃吃吃!!! } } public ...

  8. java 下溯造型_Java 的上溯造型和下溯造型以及举例,以及判断参数等指向的类

    (一) 先给出个例子,代码如下: /** * @author WangQun * 动物抽象类 */ abstract class Animal { public abstract void speak ...

  9. java 上溯造型与下塑造型

    父类: package com.neusoft.chapter07;public class Father {public int i = 1;public void say(){System.out ...

最新文章

  1. 补充知识--三相电机
  2. 22 岁专访库克、B 站 3 天涨粉百万,他将毕设树莓派扫描仪升级,繁星散落在校空!...
  3. caffe---ubuntu1604下anaconda2.5的尝试----失败,建议使用系统的python系统,避免各种各样的陷阱...
  4. unity3d v5.1.1 ugui 带垂直滚动条的文本框
  5. mysql数据库优化的几种方法
  6. 正则去除包裹的大括号
  7. 动态规划问题以及诸多实例分析
  8. 如何使用内联onclick属性停止事件传播?
  9. Vue中子组件向父组件请求数据时的数据格式问题
  10. 60套漂亮的的免费 PSD 界面设计元素包资源(系列二)
  11. centos Apache、php、mysql默认安装路径
  12. XML内容要有根标签:Extra content at the end of the document
  13. 最新视频磨皮降噪神器 轻轻松松完成视频磨皮!Beauty box
  14. tcp协议可以提供什么服务器,什么是TCP协议?
  15. linux安装硬盘安装教程,LINUX硬盘安装方法
  16. 破解tomcat管理员密码
  17. 【PHP问题解决办法】Deprecated: Function eregi() is deprecated in
  18. 图表设计-远不止“好看”这么简单
  19. 轻松禁止自动更新FLASH插件有绝招
  20. 智能手机传感器到底有什么用

热门文章

  1. 分子间相互作用力——氢键,卤键,硫键,π-π堆积,盐桥,阳离子-π,疏水作用力
  2. 《我是一只IT小小鸟》读后感,献给要正在找工作的有缘朋友
  3. 微分几何的24-33节笔记暂记(第一基本形式,第二基本形式)
  4. str.charAt(0);
  5. C语言经典问题10-计算a+aa+aaa+...的值
  6. 德国Vector维克多全系列授权or达芬奇软件
  7. RPC(远程过程调用)详解
  8. linux C 编程入门
  9. Java好学吗?现在待遇如何?
  10. 如何做好项目沟通管理的工作